導入:DataStoreに移行したい。でも怖い
Android開発を続けていると、だいたいこのタイミングが来ます。
「SharedPreferences、そろそろDataStoreにした方がいいよね」
「でも、既存データ消えたらどうしよう…」
これ、めちゃくちゃ分かります。
結論から言うと、正しい手順を踏めばDataStore移行は怖くありません。
この記事では、SharedPreferencesからDataStoreへ安全に置き換える手順と、
実務でハマりがちなポイントをまとめます。
先に結論です。
- いきなり全置き換えはしない
- 既存データの読み込み経路を確保する
- Repository層で段階的に切り替える
前提整理:SharedPreferencesとDataStoreの違い
移行の話をする前に、まず思想の違いを押さえておきます。
- SharedPreferences:同期APIあり・シンプルだが事故りやすい
- DataStore:非同期・スレッド安全・Flow前提
この違いを理解していないと、
「DataStoreにしたのに逆に複雑になった」現象が起きます。
基本的な違いについては、以下の記事で詳しく解説しています。
SharedPreferencesとDataStoreの違いと正しい使い分け
なぜDataStore移行でハマるのか
多くの失敗は、「APIの置き換え」だと思ってしまうことが原因です。
よくある勘違い
- getString → dataStore.data.map に置き換えればOK
- SharedPreferencesを消しても問題ない
- 同期処理のまま書き換えられる
DataStoreは非同期・Flow前提です。
設計ごと変えないと、確実に詰まります。
安全な移行の全体像
おすすめの移行手順は、以下の流れです。
- ① DataStoreを新規追加する
- ② SharedPreferencesを「読み取り専用」にする
- ③ DataStoreへデータをコピーする
- ④ DataStoreのみ参照する
- ⑤ SharedPreferencesを削除する
段階的に切り替えるのが最大のポイントです。
ステップ① DataStoreを追加する
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
name = "app_datastore"
)
この時点では、
まだSharedPreferencesは消しません。
ステップ② SharedPreferencesを読み取り専用にする
まずは「書き込み」を止めます。
class LegacyPref(private val context: Context) {
private val prefs =
context.getSharedPreferences("legacy_prefs", Context.MODE_PRIVATE)
fun getUserId(): String? {
return prefs.getString("user_id", null)
}
}
ここで新規保存を止めることで、
データの二重管理を防げます。
ステップ③ DataStoreへコピーする
初回起動時などで、一度だけコピーします。
suspend fun migrateIfNeeded() {
val legacyUserId = legacyPref.getUserId() ?: return
context.dataStore.edit { prefs ->
prefs[stringPreferencesKey("user_id")] = legacyUserId
}
}
ここで重要なのは、
コピー完了後に二度とSharedPreferencesを見ないことです。
ステップ④ Repository層で吸収する
UIやUseCaseから、
直接DataStoreやSharedPreferencesを触らせないようにします。
class UserRepository(
private val dataStore: DataStore<Preferences>
) {
val userIdFlow: Flow<String?> =
dataStore.data.map { it[stringPreferencesKey("user_id")] }
}
こうすることで、
保存方式を変えても影響範囲が限定されます。
実務でよくあるハマりポイント
① 同期処理の感覚が抜けない
DataStoreは基本 suspend / Flow です。
getString感覚で使うと破綻します。
② UI層でcollectしっぱなし
ライフサイクルを考えないcollectは、
メモリリークの温床です。
③ すべてnullableになる
Repositoryで初期値を補正しないと、
UIが nullable 地獄になります。
テスト・確認観点
- 既存ユーザーのデータが保持されているか
- 初回起動時のコピーが一度だけ行われるか
- DataStore未初期化時の挙動
- アプリ再起動後の値
よくある質問
Q. Proto DataStoreじゃダメ?
問題ありません。ただし移行コストは上がります。
まずはPreferences DataStoreで十分なケースが多いです。
Q. SharedPreferencesはすぐ消していい?
NGです。
移行完了・テスト完了後に削除しましょう。
まとめ
- DataStore移行は「設計変更」
- 段階的移行が安全
- Repositoryで吸収するのが正解
迷ったら:SharedPreferencesをいきなり消さない。
これだけ守れば、大事故は防げます。


コメント