SharedPreferencesからDataStoreへ移行する場合は自分でマイグレーション処理を書くことも可能ですが、多くの場合はDataStoreのproduceMigrationsの機能を使ってマイグレーションを行います。

DataStoreインスタンスを作成する場合は下記のようにContextからDataStore<Preferences>を生成します。

build.gradle.ktsに下記を追加(バージョンは2023年5月時点の最新版)

implementation(“androidx.datastore:datastore-preferences:1.0.0”)

DataStoreを扱うモジュール内で下記を定義

import android.content.Context

import androidx.datastore.core.DataStore

import androidx.datastore.preferences.SharedPreferencesMigration

import androidx.datastore.preferences.core.Preferences

import androidx.datastore.preferences.preferencesDataStore

internal const val DATA_STORE_NAME = "data_store"

internal const val PREFERENCES_NAME = “preferences”

internal val Context.dataStore: DataStore<Preferences> by preferencesDataStore(

    name = DATA_STORE_NAME,

    produceMigrations = { context ->

        listOf(

            SharedPreferencesMigration(

                context = context,

                sharedPreferencesName = PREFERENCES_NAME

            )

        )

    }

)

ここまでは調べると出てくるのですがproduceMigrationsで指定した内容で「マイグレーションが実行されるのはDataStoreの読み込みまたは書き込みが発生する時になります」。アプリを起動した時やDependencyInjectionでDataStore<Preferences>のインスタンスを生成した時点ではマイグレーションは実行されません。

またマイグレーションが実行されると「SharedPreferencesで読み書きしているXMLファイルは削除され、DataStoreのファイルのみとなります」。そのためマイグレーションする時にDataStoreの書き込みだけリリースして次のリリースでDataStoreへの読み込みをリリースしようという段階的なリリースはできません。

どういうことかと言うと

マイグレーション機能を実装済みで書き込みのみDataStoreに対応してリリース ⇒ アプリで書き込み時にマイグレーションが実行されSharedPreferencesのXMLファイルが削除 ⇒ SharedPreferencesの読み込みが発生 ⇒ SharedPreferencesのXMLファイルは削除されているので期待された値が返却されない

という状況が発生します。アプリの重要な機能に使われている場合だと致命的なインシデントになってしまいます。

produceMigrationsを使う場合は必ず読み込み書き込み両方をDataStoreに対応させてからアプリをリリースしましょう。