Android DataStore使用實(shí)例

Jetpack DataStore 是一種數(shù)據(jù)存儲(chǔ)解決方案,允許您使用協(xié)議緩沖區(qū)存儲(chǔ)鍵值對(duì)或類型化對(duì)象。DataStore 使用 Kotlin 協(xié)程和 Flow 以異步、一致的事務(wù)方式存儲(chǔ)數(shù)據(jù)。

如果您當(dāng)前在使用 SharedPreferences 存儲(chǔ)數(shù)據(jù),請(qǐng)考慮遷移到 DataStore。

這是官方文檔的前言,下面我們用一個(gè)簡(jiǎn)單的實(shí)例來達(dá)到學(xué)習(xí)的目的
新建立一個(gè)基于空activity的安卓工程,組件界面如下:


image.png

這個(gè)datastore是架構(gòu)組件之一,為了使用它你必須引入其它架構(gòu)組件

buildscript {
    ext{
        data_store_version = '1.0.0'
        coroutines_android_version = '1.5.1-native-mt'
        lifecycle_extensions_version = '2.2.0'
        lifecycle_version = '2.3.1'
    }
   ...
}

dependencies {

    //Coroutine support
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_android_version"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version"
    /////
    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_extensions_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    /////
    //Datastore Preferences
    implementation "androidx.datastore:datastore-preferences:$data_store_version"
    /////
...
}

下面是activity的所有代碼, 看看就明白了,然后看官方文檔就行,主要是得明白得引入其它架構(gòu)組件
但要注意以下容易犯錯(cuò)的點(diǎn):
/**
* 我們通過驗(yàn)證發(fā)現(xiàn),存儲(chǔ)dataStore的代碼不能在onStop和onDestroy執(zhí)行
* 而onPause則是可以的,一般是用戶退出程序存儲(chǔ)下數(shù)據(jù)是合理的,但如果在onPause存儲(chǔ)也不是一個(gè)壞事
* 畢竟我們用這個(gè)存儲(chǔ)的數(shù)據(jù)往往都是簡(jiǎn)單的配置數(shù)據(jù),很多時(shí)候僅僅是為了響應(yīng)google的推薦而已, 另外嚴(yán)格來講
* 就應(yīng)該在onPause存儲(chǔ)數(shù)據(jù),以免系統(tǒng)把我們進(jìn)程殺掉導(dǎo)致數(shù)據(jù)丟失
* 其實(shí)結(jié)論是 不能在onStop onDestroy 調(diào)用類似lifecycleScope.launch{...}樣式代碼,因?yàn)槟菚r(shí)候這個(gè)scope
* 正在被銷毀,這樣調(diào)用會(huì)導(dǎo)致括弧里代碼不執(zhí)行或者被強(qiáng)行中斷
*
*/
否則跑不起來的
DataStore | Android 開發(fā)者 | Android Developers (google.cn)

package com.sky.testdatastore

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * https://developer.android.google.cn/topic/libraries/architecture/datastore
 * 使用 Preferences DataStore 存儲(chǔ)鍵值對(duì)
 * Preferences DataStore 實(shí)現(xiàn)使用 DataStore 和 Preferences 類將簡(jiǎn)單的鍵值對(duì)保留在磁盤上。
 * 創(chuàng)建 Preferences DataStore
 * 使用由 preferencesDataStore 創(chuàng)建的屬性委托來創(chuàng)建 Datastore<Preferences> 實(shí)例。
 * 在您的 Kotlin 文件頂層調(diào)用該實(shí)例一次,便可在應(yīng)用的所有其余部分通過此屬性訪問該實(shí)例。
 * 這樣可以更輕松地將 DataStore 保留為單例。
 */
/**
 * 我們不難看出dataStore實(shí)際上是安卓架構(gòu)組件的一部分,即便僅僅為了測(cè)試
 * 我們也不得不引入其它架構(gòu)組件 協(xié)程支持 lifecycle支持
 */
// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
class MainActivity : AppCompatActivity() {
    suspend fun incrementCounter(context:Context) {
        context.dataStore.edit { settings ->
            val currentCounterValue = settings[EXAMPLE_COUNTER] ?: 0
            settings[EXAMPLE_COUNTER] = currentCounterValue + 1
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val exampleCounterFlow: Flow<Int> = this.dataStore.data
            .map { preferences ->
                // No type safety.
                preferences[EXAMPLE_COUNTER] ?: 0
            }
        //讀取datastore的值
        lifecycleScope.launchWhenStarted {
            exampleCounterFlow.collect {
                withContext(Dispatchers.Main.immediate){
                    findViewById<TextView>(R.id.textView).text = it.toString()
                }
            }
        }

        findViewById<Button>(R.id.buttonWrite)?.setOnClickListener {
            val c = this
            lifecycleScope.launch {
                incrementCounter(c)
            }
        }
        //以上 通過點(diǎn)擊write按鈕 這個(gè)counter就會(huì)一直增加 演示了dataStore的基本應(yīng)用

        /**
         * 本人認(rèn)為類型安全的方式 用于dataStore還不如用room呢,因?yàn)槲覀冏霭沧考軜?gòu)時(shí) room必然是要使用的
         * 僅僅為了測(cè)試這個(gè)玩意也沒啥意思,還挺費(fèi)勁 所以就到這里了
         */
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容