首頁>技術>

作者 / Android 開發技術推廣工程師 Florina Muntenescu 與 Google 軟體工程師 Rohit Sathyanarayana

出處:https://mp.weixin.qq.com/s?__biz=MzAwODY4OTk2Mg==&mid=2652076039&idx=1&sn=49259c54924dde908c64b6bde6ff57af

歡迎使用 Jetpack DataStore,這是一個經過改進的全新資料儲存解決方案,旨在替代原有的 SharedPreferences。Jetpack DataStore 基於 Kotlin 協程和 Flow 開發,並提供兩種不同的實現: Proto DataStorePreferences DataStore 。其中 Proto DataStore ,可以儲存帶有型別的物件 (使用 protocol buffers 實現); Preferences DataStore ,可以儲存 鍵值對 。在 DataStore 中,資料以非同步的、一致的、事務性的方式進行儲存,克服了 SharedPreferences 的大部分缺點。

protocol buffershttps://developers.google.cn/protocol-buffersSharedPreferences 和 DataStore 對比

* SharedPreferences 有一個看上去可以在 UI 執行緒安全呼叫的同步 API,但是該 API 實際上執行了磁碟 I/O 操作。此外, apply() 方法會在 fsync() 阻塞 UI 執行緒。在您應用的任何地方,每當 Service 或 Activity 啟動或停止時,就會觸發等待 fsync() 的呼叫。由 apply() 安排的 fsync() 呼叫過程會阻塞 UI 執行緒,這也常常成為造成 ANR 的源頭。

** SharedPreferences 在分析出錯時會丟擲執行時異常。

ANRhttps://developer.android.google.cn/topic/performance/vitals/anr

在兩種實現中,除非另外特指,否則 DataStore 會將首選項儲存在檔案中,並且所有的資料操作都會在 Dispatchers.IO 上執行。

雖然 Preferences DataStore 與 Proto DataStore 都可以儲存資料,但它們的實現方法不盡相同:

Preference DataStore,就像 SharedPreferences 一樣,不能定義 schema 或保證以正確的型別訪問鍵值。Proto DataStore讓您可以使用 Protocol buffers 定義 schema。使用 Protobufs 可以保留 強型別資料 。它們相對於 XML 或其他相似的資料格式要更快、更小、歧義更少。雖然 Proto DataStore 要求您學習一種新的序列化機制,但考慮到 Proto DataStore 所帶來的強型別 schema 的優勢,我們認為這樣的代價是值得的。Protocol buffershttps://developers.google.cn/protocol-buffersRoom 和 DataStore 對比

如果您有區域性更新資料、參照完整性或支援大型、複雜資料集的需求,則應當考慮使用 Room 而不是 DataStore。DataStore 是小型、簡單資料集的理想選擇,它並不支援區域性更新與參照完整性。

使用 DataStore

首先新增 D ataSt ore 依賴項。如果您使用的是 Proto DataStore,請確保您也添加了 proto 依賴項 :

proto 依賴項https://github.com/google/protobuf-gradle-plugin
def dataStoreVersion = "1.0.0-alpha05" // 在 Android 開發者網站上確認最新的版本號 // https://developer.android.google.cn/jetpack/androidx/releases/datastore// Preferences DataStoreimplementation "androidx.datastore:datastore-preferences:$dataStoreVersion"// Proto DataStoreimplementation  "androidx.datastore:datastore-core:$dataStoreVersion"

當您使用 Proto DataStore 時,您需要在 app/src/main/proto/ 目錄下使用 proto 檔案定義您自己的 schema。有關定義 proto schema 的更多資訊,請參閱 protobuf 語言指南 。

protobuf 語言指南https://developers.google.cn/protocol-buffers/docs/proto3
syntax = "proto3";option java_package = "<your package name here>";option java_multiple_files = true;message Settings {  int my_counter = 1;}

建立 DataStore

您可以使用 Context.createDataStore() 擴充套件方法建立 DataStore :

// 建立 Preferences DataStore val dataStore: DataStore<Preferences> = context.createDataStore(    name = "settings")

如果您使用的是 Proto DataStore,您還需要實現 Serializer 介面來告訴 DataStore 如何讀取和寫入您的資料型別。

object SettingsSerializer : Serializer<Settings> {    override fun readFrom(input: InputStream): Settings {        try {            return Settings.parseFrom(input)        } catch (exception: InvalidProtocolBufferException) {            throw CorruptionException("Cannot read proto.", exception)        }    }    override fun writeTo(t: Settings, output: OutputStream) = t.writeTo(output)}// 建立 Proto DataStoreval settingsDataStore: DataStore<Settings> = context.createDataStore(    fileName = "settings.pb",    serializer = SettingsSerializer)

從 DataStore 讀取資料

無論是 Preferences 物件還是您在 proto schema 中定義的物件,DataStore 都會以 Flow 的形式暴露已儲存的資料。DataStore 可以確保在 Dispatchers.IO 上檢索資料,因此不會阻塞您的 UI 執行緒。

Dispatchers.IOhttps://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-i-o.html

使用 Preferences DataStore:

val MY_COUNTER = preferencesKey<Int>("my_counter")val myCounterFlow: Flow<Int> = dataStore.data     .map { currentPreferences ->        // 不同於 Proto DataStore,這裡不保證型別安全。        currentPreferences[MY_COUNTER] ?: 0      }

使用 Proto DataStore:

val myCounterFlow: Flow<Int> = settingsDataStore.data    .map { settings ->        // myCounter 屬性由您的 proto schema 生成!        settings.myCounter     }

向 DataStore 寫入資料

為了寫入資料,DataStore 提供了一個 DataStore.updateData() 掛起函式,它會將當前儲存資料的狀態作為引數提供給您,對於 Preferences 物件或是您在 proto schema 中定義的物件例項皆為如此。 updateData() 函式使用原子的讀、寫、修改操作並以事務的方式更新資料。當資料在磁碟上完成儲存時,此協程就會完成。

Preferences DataStore 還提供了一個 DataStore.edit() 函式來方便資料的更新。在此函式中,您會收到一個用於編輯的 MutablePreferences 物件,而不是 Preferences 物件。該函式與 updateData() 一樣,會在轉換程式碼塊完成之後將修改應用到磁碟,並且當資料在磁碟上完成儲存時,此協程就會完成。

使用 Preferences DataStore:

suspend fun incrementCounter() {    dataStore.edit { settings ->        // 可以安全地增加我們的計數器,而不會因為資源競爭而丟失資料。        val currentCounterValue = settings[MY_COUNTER] ?: 0        settings[MY_COUNTER] = currentCounterValue + 1    }}

使用 Proto DataStore:

suspend fun incrementCounter() {    settingsDataStore.updateData { currentSettings ->        // 可以安全地增加我們的計數器,而不會因為資源競爭而丟失資料。        currentSettings.toBuilder()            .setMyCounter(currentSettings.myCounter + 1)            .build()    }}

從 SharedPreferences 遷移至 DataStore

要從 SharedPreferences 遷移至 DataStore,您需要將 SharedPreferencesMigration 物件傳遞給 DataStore 構造器,DataStore 可以自動完成從 SharedPreferences 遷移至 DataStore 的工作。遷移會在 DataStore 中發生任何資料訪問之前執行,這意味著在 DataStore.data 返回任何值以及 DataStore.updateData() 可以更新資料之前,您的遷移必須已經成功。

如果您要遷移至 Preferences DataStore,您可以使用 SharedPreferencesMigration 的預設實現。只需要傳入 SharedPreferences 構造時所使用的名字就可以了。

使用 Preferences DataStore:

val dataStore: DataStore<Preferences> = context.createDataStore(    name = "settings",    migrations = listOf(SharedPreferencesMigration(context, "settings_preferences")))

當需要遷移至 Proto DataStore 時,您必須實現一個對映函式,用來定義如何將 SharedPreferences 所使用的鍵值對遷移到您所定義的 DataStore schema。

使用 Proto DataStore:

val settingsDataStore: DataStore<Settings> = context.createDataStore(    produceFile = { File(context.filesDir, "settings.preferences_pb") },    serializer = SettingsSerializer,    migrations = listOf(        SharedPreferencesMigration(            context,            "settings_preferences"                    ) { sharedPrefs: SharedPreferencesView, currentData: UserPreferences ->            // 在這裡將 sharedPrefs 對映至您的型別。          }    ))
總結

SharedPreferences 有著許多缺陷: 看起來可以在 UI 執行緒安全呼叫的同步 API 其實並不安全、沒有提示錯誤的機制、缺少事務 API 等等。DataStore 是 SharedPreferences 的替代方案,它解決了 Shared Preferences 的絕大部分問題。DataStore 包含使用 Kotlin 協程和 Flow 實現的完全非同步 API,可以處理資料遷移、保證資料一致性,並且可以處理資料損壞。

由於 DataStore 仍處於測試階段,因此我們需要您的幫助以使其變得更好!首先,您可以透過我們的 文件 瞭解有關 DataStore 的更多資訊,也可以透過我們為您準備的兩個 Codelab: Preferences DataStore codelab 和 Proto DataStore codelab 來嘗試 DataStore。最後,您可以在 問題跟蹤器 上建立問題,讓我們知道如何來改進 DataStore。

出處:https://mp.weixin.qq.com/s?__biz=MzAwODY4OTk2Mg==&mid=2652076039&idx=1&sn=49259c54924dde908c64b6bde6ff57af

16
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • MybatisPlus全套Api小解(一)