I have seen this blog https://medium.com/androiddevelopers/datastore-and-data-migration-fdca806eb1aa, but it is not quite detail. It does not show how to do data migration of proto datastore plus how you do it using Dagger Hilt.
This is what I have done so far.
I have a AppSettings (like AppPreferences)
@Serializable
data class AppSettings(
val prepareSeconds: Long = 10L,
val workSeconds: Long = 90L,
val restSeconds: Long = 30L,
val totalSets: Int = 3
) {
companion object {
fun getDefaultInstance() = AppSettings()
}
}
Serialiser (I don’t use .proto file, I have a Preferences Data Class & deserialize and serialize it)
object AppSettingsSerializer : Serializer<AppSettings> {
override val defaultValue: AppSettings
get() = AppSettings()
override suspend fun readFrom(input: InputStream): AppSettings {
return try {
Json.decodeFromString(
deserializer = AppSettings.serializer(),
string = input.readBytes().decodeToString()
)
} catch (e: SerializationException) {
throw CorruptionException("Unable to read AppSettingsPrefs", e)
}
}
@Suppress("BlockingMethodInNonBlockingContext")
override suspend fun writeTo(t: AppSettings, output: OutputStream) {
output.write(
Json.encodeToString(
serializer = AppSettings.serializer(),
value = t
).encodeToByteArray()
)
}
}
Dagger Hilt Module finally
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideAppSettingsDataStore(
@ApplicationContext appContext: Context,
coroutineScope: CoroutineScope,
): DataStore<AppSettings> {
return DataStoreFactory.create(
serializer = AppSettingsSerializer,
corruptionHandler = ReplaceFileCorruptionHandler {
AppSettings.getDefaultInstance()
},
scope = coroutineScope,
produceFile = {
appContext.dataStoreFile(DATA_STORE_FILE_NAME)
},
migrations = listOf(object : DataMigration<AppSettings> {
// Specify your condition for whether the migration should happen
override suspend fun shouldMigrate(currentData: AppSettings) = true
// Instruction on how exactly the old data is transformed into new data
// I DO NOT THINK THIS IS RIGHT WAY TO DO IT, HOW SHOULD IT BE DONE??
override suspend fun migrate(currentData: AppSettings): AppSettings =
AppSettings(
prepareSeconds = currentData.prepareSeconds,
workSeconds = currentData.workSeconds,
restSeconds = currentData.restSeconds,
totalSets = currentData.totalSets,
)
// Once the migration is over, clean up the old storage
override suspend fun cleanUp() = Unit
})
)
}
When I update AppSettings (Preferences) with new field/update existing field name/ delete some field. Then DataStore not do migration but re-intialise with default value.
What I am doing wrong. Can anyone give me any resources/blog or code on how to do data migration of proto datastore using Dagger Hilt.