rcosteira79/android-skills

datastore

Use when persisting key-value preferences or small typed settings on Android or KMP with Jetpack DataStore — Preferences vs Typed (Proto/JSON) vs Room selection, the IOException and corruption-recovery error traps, serializers with corruption handlers, and…

Ver código-fonte

Como usar

  1. Copie o comando e verifique o pacote antes de instalar no seu ambiente de agente.
  2. Consulte no original as ferramentas, credenciais e ambientes necessários.
  3. Descreva os dados de entrada e a entrega esperada; confira a saída com as fontes.
npx skills add https://github.com/rcosteira79/android-skills --skill datastore

Antes de começar

  • A instalação não inclui assinatura de modelo, franquia API ou acesso aos seus arquivos.
  • Estrelas e instalações indicam atividade, não um teste independente de qualidade ou segurança.
Documento original do Skill

Renderizado do repositório de origem, preservando títulos, exemplos, código, tabelas, links e imagens.

Jetpack DataStore for Android and KMP

Reactive coroutine-based key-value / typed storage; the same androidx.datastore:datastore-preferences-core runs on Android, iOS, and JVM — only the file-path producer is platform-specific. (Web support is 1.3.0-alpha only, and it's sessionStorage/OPFS-backed there, not file-path-based.) This reference covers the storage-choice call plus the two error/path traps, not the basics of Preferences keys, edit { }, or Serializer<T>. Adapted from Meet-Miyani/compose-skill; MIT. Related: android-skills:android-data-layer, android-skills:kmp-boundaries, android-skills:kotlin-flows.

Preferences vs Typed vs Room

NeedStorage
Key-value flags (theme, locale, onboarding done)Preferences DataStore
One typed object, many related fields, schema evolutionTyped DataStore + Serializer<T>
Relational data, indexes, WHERE / JOIN, >100 entries, pagingRoom
Payloads above ~50KB per writeRoom / filesystem — DataStore rewrites the whole file on every edit

Rule of thumb: if a WHERE clause would be useful, use Room.

The two traps

`.catch` must match `IOException` specifically — never a broad `catch`. A bare catch { emit(emptyPreferences()) } swallows CancellationException (breaking structured concurrency) and hides serializer/corruption errors behind a silent empty state.

kotlin
val settings: Flow<UserSettings> = dataStore.data
    .catch { e -> if (e is IOException) emit(emptyPreferences()) else throw e }
    .map { p -> UserSettings(p[Keys.DARK_MODE] ?: false, p[Keys.LOCALE] ?: "en") }

Typed-DataStore corruption recovery triggers on `CorruptionException`, NOT `IOException`. The serializer's readFrom must wrap parse failures in CorruptionException, and the store needs a ReplaceFileCorruptionHandler — without it, one corrupt file makes every read fail permanently.

kotlin
object AppSettingsSerializer : Serializer<AppSettings> {
    override val defaultValue = AppSettings()
    override suspend fun readFrom(input: InputStream): AppSettings =
        try { Json.decodeFromString(input.readBytes().decodeToString()) }
        catch (e: SerializationException) { throw CorruptionException("Cannot read AppSettings", e) }
    override suspend fun writeTo(t: AppSettings, output: OutputStream) =
        output.write(Json.encodeToString(t).encodeToByteArray())
}
val store = DataStoreFactory.create(
    serializer = AppSettingsSerializer,
    corruptionHandler = ReplaceFileCorruptionHandler { AppSettings() },
    produceFile = { File(context.filesDir, "app_settings.json") },
)

KMP factory — per-platform path (not the temp dir)

kotlin
// commonMain
fun createPreferencesDataStore(producePath: () -> String): DataStore<Preferences> =
    PreferenceDataStoreFactory.createWithPath(produceFile = { producePath().toPath() })
// android: context.filesDir.resolve(PREFS_FILE).absolutePath
// ios:     NSDocumentDirectory via NSFileManager
// jvm:     File(System.getProperty("user.home"), ".myapp") — NOT java.io.tmpdir (the OS may wipe it on reboot)

(In a composable, never runBlocking on DataStore — it parks the main thread on disk I/O, risking an ANR, and re-runs every recomposition. Expose a StateFlow and collect with collectAsStateWithLifecycle.)

Relacionados por tarefa

do mesmo repositório

Mais Skills

Todos os Skills
rcosteira79
Comunidade

android-data-layer

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).

instalações
1
GitHub Stars
155
Atualizado
19 de set.
rcosteira79
Comunidade

android-debugging

Use when debugging Android or KMP issues — Android-specific techniques covering Logcat, ADB, ANR traces, R8 stack trace decoding, memory leaks, Gradle build failures, and Compose recomposition bugs, on a root-cause-first foundation.

instalações
1
GitHub Stars
155
Atualizado
19 de set.
rcosteira79
Comunidade

android-dev

Use this skill as the baseline for ALL Android and Kotlin Multiplatform (KMP) work — whenever the user mentions Android, Kotlin (in an Android context), KMP, CMP, commonMain, androidMain, iosMain, AndroidManifest, Gradle, build.gradle, Hilt, Dagger, Room, Retrofit, Ktor, ViewModel, LiveData, StateFlow, SharedFlow, Compose, Activity, Fragment, Intent, ADB, Logcat, MVVM, MVI, repository pattern, or any Android SDK / Jetpack / AndroidX API. Always load this skill alongside the more specific skills

instalações
1
GitHub Stars
155
Atualizado
19 de set.
rcosteira79
Comunidade

android-ux

Use when designing or reviewing Android UI — applies Material Design 3 UX principles covering touch targets, spacing, navigation patterns, accessibility, animation timing, and platform conventions. Includes an M3 compliance audit that scores screens across 10 categories. Complements the compose skill with design-level decisions.

instalações
1
GitHub Stars
155
Atualizado
19 de set.