如何使用 Dagger Hilt 进行原始数据存储到原始数据存储的迁移

问题描述 投票:0回答:1

我看过这个博客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 进行原始数据存储的数据迁移的资源/博客或代码。

android migration dagger-hilt proto-datastore
1个回答
0
投票

这种情况很可能仅在您从 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()
            )
© www.soinside.com 2019 - 2024. All rights reserved.