我看过这个博客https://medium.com/androiddevelopers/datastore-and-data-migration-fdca806eb1aa,但是不太详细。它没有展示如何进行原始数据存储的数据迁移以及如何使用 Dagger Hilt 进行数据迁移。
这就是我到目前为止所做的。 我有一个 AppSettings(如 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()
}
}
序列化器(我不使用 .proto 文件,我有一个首选项数据类并反序列化和序列化它)
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()
)
}
}
终于有了匕首柄模块
@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
})
)
}
当我使用新字段更新 AppSettings(首选项)/更新现有字段名称/删除某些字段时。然后DataStore不进行迁移而是使用默认值重新初始化。
我做错了什么。谁能给我任何关于如何使用 Dagger Hilt 进行原始数据存储的数据迁移的资源/博客或代码。
这种情况很可能仅在您从 DataStore 中删除某些字段时发生。因此,您的反序列化器会抛出
CorruptionException
并在 CorruptionHandler 中创建新的 AppSettings 实例。要解决此问题,您需要指示 json 忽略未知键(在 AppSettings 中不再使用)。
val json = Json { ignoreUnknownKeys = true } // Ignore unknown keys to prevent errors when removing some parameters
return json.decodeFromString(
UserPreferences.serializer(), input.readBytes().decodeToString()
)