JetPack

Jetpack DataStore详解

2020-12-15  本文已影响0人  不做android

DataStore出现的原因

Jetpack DataStore is a data storage solution that allows you to store key-value pairs or typed objects with protocol buffers. DataStore uses Kotlin coroutines and Flow to store data asynchronously, consistently, and transactionally.
If you're currently using SharedPreferences to store data, consider migrating to DataStore instead.


 官方文档给出的定义如上所示


DataStore的实现方式

DataStore provides two different implementations: Preferences DataStore and Proto DataStore.


 文档中给出DataStore的两种实现方式:


DataStore的使用

// Preferences DataStore
    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha03"
// Proto DataStore
    implementation "androidx.datastore:datastore-core:1.0.0-alpha03"
private val DATASTORE_NAME = "hy_datastore"
var dateStore: DataStore<Preferences> = mContext.createDataStore(name = DATASTORE_NAME)
public suspend fun DataStore<Preferences>.edit(
    transform: suspend (MutablePreferences) -> Unit
): Preferences {
    return this.updateData {
        // It's safe to return MutablePreferences since we freeze it in
        // PreferencesDataStore.updateData()
        it.toMutablePreferences().apply { transform(this) }
    }
}

可以看到edit()方法是一个suspend函数,所以只能在协程体中进行调用。以挂起的方式进行运行,做到不阻碍主线程。

private suspend fun saveDate(data: String) {
        mDataStorePre.edit { mutablePreferences ->
            mutablePreferences[KEY_TEST_DATASTORE] = ""
        }
    }
private suspend fun getDate(data: String): String {
        var value = mDataStorePre.data.map { preferences ->
            preferences[KEY_TEST_DATASTORE] ?: ""
        }
        return value.first()
    }

可以看到DataStore的key不同于spkey,DataStore的keyPreferences.Key<T>类型,只支持Int,Long,Boolean,Float,String,Double

public inline fun <reified T : Any> preferencesKey(name: String): Preferences.Key<T> {
    return when (T::class) {
        Int::class -> {
            Preferences.Key<T>(name)
        }
        String::class -> {
            Preferences.Key<T>(name)
        }
        Boolean::class -> {
            Preferences.Key<T>(name)
        }
        Float::class -> {
            Preferences.Key<T>(name)
        }
        Long::class -> {
            Preferences.Key<T>(name)
        }
        Double::class -> {
            Preferences.Key<T>(name)
        }
        Set::class -> {
            throw IllegalArgumentException("Use `preferencesSetKey` to create keys for Sets.")
        }
        else -> {
            throw IllegalArgumentException("Type not supported: ${T::class.java}")
        }
    }
}
除此外的类型将会抛出异常。
private suspend fun getDate(): String {
        var value = mDataStorePre.data.catch {
            if (it is IOException) {//io异常的话可以发送一个emptyPreferences()来重新使用
                it.printStackTrace()
                emit(emptyPreferences())
            } else {
                throw it
            }
        }
                .map { preferences ->
                    preferences[KEY_TEST_DATASTORE] ?: ""
                }
        return value.first()

    }

迁移Sp到DataStore

只需要在创建的时候传入需要迁移的SharedPreferencesMigration如下:

var mDataStorePre: DataStore<Preferences> = mContext.createDataStore(
                name = DATASTORE_NAME,
                migrations = listOf(
                        SharedPreferencesMigration(
                                mContext,
                                SPUtil.NAME
                        )
                )
        )
上一篇 下一篇

猜你喜欢

热点阅读