Y&S SoftWareのホームページ
使いかってのいいソフトウェアを開発します

DataStore の使い方

DataStore の使い方について


@
JSON 文字列にまとめて保存する方式

val getLastOpenFileMap: Flow> = context.dataStore.data
  .map { preferences ->
    val json = preferences[LAST_OPEN_FILE_MAP] ?: "{}"
    Gson().fromJson(json, type)
  }

suspend fun saveLastOpenFile(folderId: Int, fileId: Int) {
  context.dataStore.edit { preferences ->
    val currentJson = preferences[LAST_OPEN_FILE_MAP] ?: "{}"
    val currentMap = Gson().fromJson(currentJson, type) ?: mutableMapOf()
    currentMap[folderId] = fileId
    preferences[LAST_OPEN_FILE_MAP] = Gson().toJson(currentMap)
  }
}


特徴

Map を JSON にして 1 つのキーにまとめて保存

保存・取得のたびに Gson で シリアライズ/デシリアライズ が必要

データ構造を自由に作れる(Map, List, ネスト構造など)

メリット

複数のデータを 一括で管理 できる

「folderId → fileId」みたいな 関連づけが必要な場合に便利

データ形式を変えても 1 キーで済む

デメリット

JSON のパース処理が必要(オーバーヘッドあり)

更新時は 全体を再シリアライズして書き戻す必要あり

一部だけ更新したい場合でも全体を扱うので冗長




A
PreferencesKey を個別に作って保存する方式
object ScrollKeys {
  fun keyForFile(fileId: Int) = intPreferencesKey("scroll_position_$fileId")
}

suspend fun saveScrollPosition(fileId: Int, position: Int) {
  context.dataStore.edit { prefs ->
    prefs[ScrollKeys.keyForFile(fileId)] = position
  }
}

suspend fun getScrollPosition(fileId: Int): Int? {
  val prefs = context.dataStore.data.first()
  return prefs[ScrollKeys.keyForFile(fileId)]
}


特徴

fileId ごとに 専用のキーを作成 (scroll_position_123 みたいに)

値はプリミティブ(Int, Boolean, String…)のみ

JSON 変換不要 → 直接保存・取得

メリット

実装がシンプルで効率的(パース不要)

個別の値を直接更新できる(Map 全体を再保存する必要なし)

DataStore の思想に近い使い方

デメリット

キーが多くなる(ファイル数が多いと "scroll_position_1000" みたいに増える)

「まとめて全部のスクロール位置を取りたい」ときにやや不便

複雑な構造には向かない



どちらを選ぶのか

単純に「ファイルごとのスクロール位置」を保存したい → A(個別キー方式)が最適

軽量・高速・シンプル



「フォルダID → 最後に開いたファイルID」のように関係を管理したい → @(JSON 方式)が向いている

Map で保存して一括管理できる




まとめ

@ JSON 方式 = 複雑なデータ構造をまとめたいとき(Map, List など)

A 個別キー方式 = シンプルに「ID → 値」を直接保存したいとき