android-data-layer
/android-data-layer
Pomaga implementować warstwę danych w Androidzie i KMP: wzorzec Repository z propagacją błędów, sealed DataError, Result oraz Room w commonMain.
- Autor
- rcosteira79 ↗
- Repozytorium
- android-skills ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 19.09.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 1
- Skrypty
- 0
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 0
Brak sygnałów. Repozytorium zmienione 19.09.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
Co robi i kiedy
Pomaga implementować warstwę danych w Androidzie i KMP: wzorzec Repository z propagacją błędów, sealed DataError, Result oraz Room w commonMain.
Oryginalny opis (EN)
Use when implementing the data layer in Android or KMP — the Repository pattern's layered error-propagation model (repository as the error boundary, sealed DataError, Result placement with and without a domain layer) and Room in commonMain (@ConstructedBy, BundledSQLiteDriver, per-target KSP).
Jak działa
- Error propagation — the layered model
- Room in KMP (commonMain)
Podgląd SKILL.md
---
name: android-data-layer
description: Use when implementing the data layer in Android or KMP — the Repository pattern's layered error-propagation model (repository as the error boundary, sealed DataError, Result placement with and without a domain layer) and Room in commonMain (@ConstructedBy, BundledSQLiteDriver, per-target KSP).
---
# Android Data Layer
The data layer coordinates data from multiple sources; its public API is repository interfaces, and its internals (DAOs, API services, DTOs) never leak upward. This skill is the canonical home for the **error-propagation model**, plus the KMP-Room setup. **Related:** `android-skills:android-retrofit` (Retrofit service/OkHttp/Hilt wiring), `android-skills:android-dev` (overall app architecture).
## Error propagation — the layered model
The goal: data-layer errors (`IOException` / `HttpException` / `SQLiteException`) must never reach the ViewModel. Map them to a domain error type at the repository boundary. If the project already has an error convention, match it; otherwise a sealed `DataError` hierarchy is a reasonable default:
```kotlin
sealed class DataError(message: String, cause: Throwable? = null) : Exception(message, cause) {
class Network(cause: Throwable) : DataError("Network error", cause)
class Server(val code: Int, message: String?) : DataError("Server error $code: $message")
class Local(cause: Throwable) : DataError("Local storage error", cause)
}
// repository = error boundary: catch platform exceptions, return Result<T> (no domain layer) or throw DataError (with one)
suspend fun refreshNews(): Result<Unit> = withContext(io) {
try { newsDao.insertAll(newsApi.fetchLatest().map(NewsDto::toEntity)); Result.success(Unit) }
catch (e: IOException) { Result.failure(DataError.Network(e)) }
catch (e: HttpException) { Result.failure(DataError.Server(e.code(), e.message())) }
}
```
The boundary moves outward by one layer when a domain layer exists:
1. **Data sources** throw platform/library exceptions (`IOException`, `HttpException`, `SQLiteException`).
2. **Repository** is the error boundary — catch those and remap to `DataError`; never let raw platform types leak. *Without a domain layer (simple MVVM):* the repository returns `Result<T>` directly and the ViewModel handles it without knowing about platform exceptions.
3. **Use cases** (when present) are the `Result` boundary — the repository instead *throws* `DataError`, and the use case catches it and returns `Result<T>` with a domain-specific error model. Use cases never catch platform exception types.
4. **ViewModels** handle `Result<T>` and map it to UI state (explicit loading / success / error).
(Default to the `Entity` suffix — `ArticleEntity` — for Room types; match an existing convention such as a `Cached` prefix if the project already uses one.)
## Room in KMP (`commonMain`)
Room has been KMP-stable since 2.7.0. The shared setup differs from the Android-only setup in three places:
1. **`@ConstructedBy(...)`** on the `@Database`, paired with an `expect object` Room generates per-platform `actual`s for.
2. **`BundledSQLiteDriver`** (from `androidx.sqlite:sqlite-bundled`) — pins the same SQLite version across Android/iOS/JVM/web (Android's system SQLite drifts between API levels and devices).
3. **`setQueryCoroutineContext(Dispatchers.IO)`** — Android Room defaults this; KMP doesn't.
```kotlin
// commonMain
@Database(entities = [ArticleEntity::class], version = 1, exportSchema = true)
@ConstructedBy(AppDatabaseConstructor::class)
abstract class AppDatabase : RoomDatabase() { abstract fun articleDao(): ArticleDao }
@Suppress("KotlinNoActualForExpect")
expect object AppDatabaseConstructor : RoomDatabaseConstructor<AppDatabase>
fun getRoomDatabase(builder: RoomDatabase.Builder<AppDatabase>): AppDatabase =
builder.setDriver(BundledSQLiteDriver()).setQueryCoroutineContext(Dispatchers.IO).build()
```
Each platform provides its own builder — Android `Room.databaseBuilder(context, AppDatabase::class.java, "app.db")`; iOS/JVM `Room.databaseBuilder<AppDatabase>(databasePath = …)`. **KSP must be wired per target** (`ksp(libs.androidx.room.compiler)` is Android-only):
```kotlin
dependencies {
add("kspAndroid", libs.androidx.room.compiler)
add("kspIosArm64", libs.androidx.room.compiler)
add("kspIosSimulatorArm64", libs.androidx.room.compiler)
// … one per target
}
room { schemaDirectory("$projectDir/schemas") } // export the schema for migration-history tracking
```
For pure-Android projects, skip `@ConstructedBy` and call `Room.databaseBuilder(context, AppDatabase::class.java, "app.db")` directly — Room behaves identically; the KMP setup is opt-in when the data layer must live in `commonMain`.
Wersje
W bazie nie ma innych skilli o nazwie android-data-layer.
Migawka bazy z 13.11.2026 · wersja paczki bd9f6239dfbb (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100error-handling-result
Opisuje typowaną obsługę błędów w Kotlin/KMP: kotlin.Result i runCatching, sealed result types oraz Arrow Either, builder either i Raise DSL. - 95kmp-di
Konfiguruje wstrzykiwanie zależności w Kotlin Multiplatform: wspólne moduły Koin w commonMain, moduły expect/actual, start initKoin() na Androidzie i iOS oraz użycie grafu z Swifta. - 100android-clean-architecture
Stosuje wzorce Clean Architecture w projektach Android i Kotlin Multiplatform: strukturę modułów, reguły zależności, UseCase'y i warstwę danych. - 100android-dev
Stanowi bazę dla całej pracy nad Androidem i Kotlin Multiplatform: Gradle, Hilt, Room, Retrofit, Ktor, ViewModel, Compose, wzorce MVVM i MVI oraz API Jetpack i AndroidX. - 90matrixscan-batch-kmp
Integruje Scandit MatrixScan Batch w projektach KMP: śledzenie i skanowanie wielu kodów kreskowych naraz we wspólnym kodzie commonMain. - 100kotlin-multiplatform
Pomaga przy Kotlin Multiplatform: współdzielony moduł, logika biznesowa, sieć i warstwa danych między Androidem a iOS, deklaracje expect i actual, Ktor, SQLDelight, wspólny ViewModel i testy.