Android DataStore:安全存儲和輕松管理數據

關于作者:CSDN內容合伙人、技術專家, 從零開始做日活千萬級APP。
專注于分享各領域原創系列文章 ,擅長java后端、移動開發、人工智能等,希望大家多多支持。

目錄

  • 一、導讀
  • 二、概覽
  • 三、使用
    • 3.1 Preferences DataStore
      • 添加依賴
      • 數據讀寫
    • 3.2 ProtoDataStore
      • 添加依賴
      • 數據讀寫
    • 3.3、在同步代碼中使用 DataStore
    • 3.4、在多進程代碼中使用 DataStore
  • 四、DataStore & MMKV
  • 五、 推薦閱讀

在這里插入圖片描述

一、導讀

我們繼續總結學習Java基礎知識,溫故知新。

二、概覽

DataStore 是一種用于 Android 應用程序數據存儲的新的推薦方式。
它是在 Android Jetpack 組件中引入的,旨在替代 SharedPreferences,并提供更強大、易于使用的 API。

DataStore 基于 Kotlin 協程和 Flow 構建而成, 提供了一種類型安全且異步的數據存儲解決方案。
相比于 SharedPreferences,DataStore 具有以下優點:

  1. 異步操作:DataStore 提供了異步的讀寫操作,避免了阻塞主線程的問題。這使得在讀取和寫入數據時,應用程序可以更好地保持響應性能。

  2. 類型安全:DataStore 支持使用協議緩沖區(Protocol Buffers)來定義數據模型,這樣可以確保在編譯時進行類型檢查。數據模型的更改不會導致運行時錯誤,而是在編譯時進行檢測。

  3. 支持多種數據類型:DataStore 支持存儲不同類型的數據,包括原始類型、對象或自定義類。

  4. 數據一致性:DataStore 提供了一致性和安全性保證,保證在多個寫入操作中的數據一致性。

  5. 流式數據訪問:DataStore 支持使用流(Flow)來訪問數據,使得可以輕松地觀察數據的變化并進行相應的更新。

DataStore 提供了兩個主要的實現方式:PreferencesDataStore 和 ProtoDataStore。
PreferencesDataStore 適用于存儲簡單的數據類型,使用鍵值對來存儲數據。
ProtoDataStore 則使用 Protocol Buffers 定義數據模型,并支持存儲更復雜的數據結構(類型化對象)。

三、使用

3.1 Preferences DataStore

適用于存儲簡單的數據類型,使用鍵值對來存儲數據

添加依賴

    // Preferences DataStore (SharedPreferences like APIs)dependencies {implementation "androidx.datastore:datastore-preferences:1.0.0"// optional - RxJava2 supportimplementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0"// optional - RxJava3 supportimplementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"}// Alternatively - use the following artifact without an Android dependency.dependencies {implementation "androidx.datastore:datastore-preferences-core:1.0.0"}

數據讀寫

RxDataStore<Preferences> dataStore =new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();Preferences.Key<Integer> EXAMPLE_COUNTER = PreferencesKeys.int("example_counter");Flowable<Integer> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(EXAMPLE_COUNTER));Single<Preferences> updateResult =  dataStore.updateDataAsync(prefsIn -> {MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();Integer currentInt = prefsIn.get(INTEGER_KEY);mutablePreferences.set(INTEGER_KEY, currentInt != null ? currentInt + 1 : 1);return Single.just(mutablePreferences);
});
// The update is completed once updateResult is completed.

3.2 ProtoDataStore

使用 Protocol Buffers 定義數據模型,并支持存儲更復雜的數據結構

添加依賴

    // Typed DataStore (Typed API surface, such as Proto)dependencies {implementation "androidx.datastore:datastore:1.0.0"// optional - RxJava2 supportimplementation "androidx.datastore:datastore-rxjava2:1.0.0"// optional - RxJava3 supportimplementation "androidx.datastore:datastore-rxjava3:1.0.0"}// Alternatively - use the following artifact without an Android dependency.dependencies {implementation "androidx.datastore:datastore-core:1.0.0"}

數據讀寫

Proto DataStore 要求在 app/src/main/proto/ 目錄的 proto 文件中保存預定義的架構。
此架構用于定義在 Proto DataStore 中保存的對象的類型。

syntax = "proto3";option java_package = "com.example.application";
option java_multiple_files = true;message Settings {int32 example_counter = 1;
}
private static class SettingsSerializer implements Serializer<Settings> {@Overridepublic Settings getDefaultValue() {Settings.getDefaultInstance();}@Overridepublic Settings readFrom(@NotNull InputStream input) {try {return Settings.parseFrom(input);} catch (exception: InvalidProtocolBufferException) {throw CorruptionException(Cannot read proto., exception);}}@Overridepublic void writeTo(Settings t, @NotNull OutputStream output) {t.writeTo(output);}
}RxDataStore<Byte> dataStore =new RxDataStoreBuilder<Byte>(context, /* fileName= */ "settings.pb", new SettingsSerializer()).build();Flowable<Integer> exampleCounterFlow =dataStore.data().map(settings -> settings.getExampleCounter());Single<Settings> updateResult = dataStore.updateDataAsync(currentSettings ->Single.just(currentSettings.toBuilder().setExampleCounter(currentSettings.getExampleCounter() + 1).build()));    

3.3、在同步代碼中使用 DataStore

DataStore 的主要優勢之一是異步 API,但可能不一定始終能將周圍的代碼更改為異步代碼。如果您使用的現有代碼庫采用同步磁盤 I/O,或者您的依賴項不提供異步 API,就可能出現這種情況。

Kotlin 協程提供 runBlocking() 協程構建器,以幫助消除同步與異步代碼之間的差異。您可以使用 runBlocking() 從 DataStore 同步讀取數據。RxJava 在 Flowable 上提供阻塞方法。以下代碼會阻塞發起調用的線程,直到 DataStore 返回數據:

Settings settings = dataStore.data().blockingFirst();dataStore.data().first().subscribe();
這樣,DataStore 可以異步讀取數據并將其緩存在內存中。以后使用 runBlocking() 進行同步讀取的速度可能會更快,或者如果初始讀取已經完成,可能也可以完全避免磁盤 I/O 操作。
  • 請盡可能避免在 DataStore 數據讀取時阻塞線程。阻塞界面線程可能會導致 ANR 或界面卡頓,而阻塞其他線程可能會導致死鎖。

3.4、在多進程代碼中使用 DataStore

  • DataStore 多進程功能目前僅在 1.1.0 Alpha 版中提供

為了能夠在不同進程中使用 DataStore,需要使用 MultiProcessDataStoreFactory 構造 DataStore 對象。

val dataStore: DataStore<Settings> = MultiProcessDataStoreFactory.create(serializer = SettingsSerializer(),produceFile = {File("${context.cacheDir.path}/myapp.preferences_pb")}
)

四、DataStore & MMKV

看一組數據對比,圖片來源于MMKV 開源網站
在這里插入圖片描述

在這里插入圖片描述

至于如何使用就不描述了,非常簡單。
個人感覺 DataStore 沒有 MMKV 好用,推薦使用 MMKV,但是各有優劣吧。

jetpack 官網
datastore

五、 推薦閱讀

Java 專欄

SQL 專欄

數據結構與算法

Android學習專欄

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41496.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41496.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41496.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LVS負載均衡集群-NAT模式部署

集群 集群&#xff1a;將多臺主機作為一個整體&#xff0c;然后對外提供相同的服務 集群使用場景&#xff1a;高并發的場景 集群的分類 1.負載均衡器集群 減少響應延遲&#xff0c;提高并發處理的能力 2&#xff0c;高可用集群 增強系統的穩定性可靠性&…

封裝vue2局部組件都要注意什么

一. 關于局部組件組成的三個部分&#xff08;template, script, style&#xff09; template > 組件的模板結構 &#xff08;必選&#xff09; 每個組件對應的模板結構&#xff0c;需要定義到template節點中 <template><!-- 當前組件的dom結構&#xff0c;需…

Java SPI加載機制

SPI加載機制 SPI&#xff08;Service Provider Interface&#xff09;是一種通過外界配置來加載具體代碼內容的技術手段。SPI是JDK內置的一種服務提供發現機制&#xff0c;用于實現框架的擴展和組件替換。 在SPI中&#xff0c;框架提供一整套接口&#xff0c;使用者實現這些接…

React源碼解析18(8)------ 實現單節點的Diff算法

摘要 經過之前的幾篇文章&#xff0c;我們已經實現了一個可以進行更新渲染的假React。但是如果我們把我們的jsx修改成這樣&#xff1a; function App() {const [age, setAge] useState(20)const click function() {setAge(age 1)}return age % 2 0 ? jsx("div"…

學習紅外成像儀開發注意要點

學習紅外成像儀開發注意要點 三河凡科科技飛訊紅外成像儀開發學習注意要點 紅外成像儀是一種高級的光學設備&#xff0c;可用于探測、分析和顯示紅外輻射&#xff0c;它廣泛應用于醫學、軍事、石油、礦產資源勘探等領域。紅外成像儀的開發需要注意以下幾個方面&#xff1a; 1…

(搜索) 劍指 Offer 12. 矩陣中的路徑 ——【Leetcode每日一題】

?劍指 Offer 12. 矩陣中的路徑 難度&#xff1a;中等 給定一個 m * n 二維字符網格 board 和一個字符串單詞 word 。如果 word 存在于網格中&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 單詞必須按照字母順序&#xff0c;通過相鄰的單元格內的字母構…

使用Rust編寫的一款使用遺傳算法、神經網絡、WASM技術的模擬生物進化的程序

模擬生物進化程序 Github地址&#xff1a;FishLife 期待各位的star??? 本項目是一個模擬生物進化的程序&#xff0c;利用遺傳算法、神經網絡技術對魚的眼睛和大腦進行模擬。該項目是使用 Rust 語言編寫的&#xff0c;并編譯為 WebAssembly (Wasm) 格式&#xff0c;使其可以…

QT學習方法

1 .類的學習方法 第一步:從UI文件中,找到界面的類—QMainWindow第二步:在Qt Creator工具中,找到“幫助”按鈕,進入到幫助菜單界面,在選擇"索引",在Look for:輸入類名,找到類名,雙擊條目中的類名,在右側會顯示出來類的詳細內容第三步:在右側,可根據內容目錄…

Spring項目使用Redis限制用戶登錄失敗的次數以及暫時鎖定用戶登錄權限

文章目錄 背景環境代碼實現0. 項目結構圖&#xff08;供參考&#xff09;1. 數據庫中的表&#xff08;供參考&#xff09;2. 依賴&#xff08;pom.xml&#xff09;3. 配置文件&#xff08;application.yml&#xff09;4. 配置文件&#xff08;application-dev.yml&#xff09;5…

Camera Link 接口

Camera Link是一個標準的接口協議&#xff0c;用于高速的圖像數據傳輸&#xff0c;常被用在工業相機和圖像處理系統之間。這個標準由自動視覺協會&#xff08;Automated Imaging Association&#xff0c;簡稱AIA&#xff09;在2000年發布&#xff0c;旨在實現各種廠家之間的高性…

在ubuntu+cpolar+rabbitMQ環境下,實現mq服務端遠程訪問

文章目錄 前言1.安裝erlang 語言2.安裝rabbitMQ3. 內網穿透3.1 安裝cpolar內網穿透(支持一鍵自動安裝腳本)3.2 創建HTTP隧道 4. 公網遠程連接5.固定公網TCP地址5.1 保留一個固定的公網TCP端口地址5.2 配置固定公網TCP端口地址 前言 RabbitMQ是一個在 AMQP(高級消息隊列協議)基…

使用opencv4.7.0部署yolov5

yolov5原理和部署原理就不說了&#xff0c;想了解的可以看看這篇部署原理文章 #include <fstream> #include <sstream> #include <iostream> #include <opencv2/dnn.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp>/…

【Java轉Go】快速上手學習筆記(二)之基礎篇一

目錄 創建項目數據類型變量常量類型轉換計數器鍵盤交互流程控制代碼運算符 創建項目 上篇我們安裝好了Go環境&#xff0c;和用IDEA安裝Go插件來開發Go項目&#xff1a;【Java轉Go】快速上手學習筆記&#xff08;一&#xff09;之環境安裝篇 。 這篇我們開始正式學習Go語言。我…

MyBatis動態SQL:打造靈活可變的數據庫操作

目錄 if標簽trim標簽where標簽set標簽foreach標簽 動態SQL就是根據不同的條件或需求動態地生成查詢語句&#xff0c;比如動態搜索條件、動態表或列名、動態排序等。 if標簽 在我們填寫一些信息時&#xff0c;有些信息是必填字段&#xff0c;有的則是非必填的&#xff0c;這些…

淘寶API接口的實時數據和緩存數據區別

電商API接口實時數據是指通過API接口獲取到的與電商相關的實時數據。這些數據可以包括商品庫存、訂單狀態、銷售額、用戶活躍度等信息。 通過電商API接口&#xff0c;可以實時獲取到電商平臺上的各種數據&#xff0c;這些數據可以幫助企業或開發者做出及時的決策和分析。例如&…

vue動態修改audio地址

問題&#xff1a;點擊后替換url地址&#xff0c;實現了&#xff0c;但是播放器依舊沒有反應。 解決&#xff1a;vue中動態替換只是替換了地址&#xff0c;并沒有告訴audio標簽是否要執行&#xff0c;執行什么操作。要load后才能讓它知道&#xff0c;是在喊他&#xff0c;他需求…

秒懂算法 | 漢諾塔問題與木棒三角形

在數學與計算機科學中&#xff0c;遞歸(recursion)是指一個過程或函數在其定義或說明中又直接或間接調用自身的一種方法。它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復計算&#x…

Android性能優化——線程優化

一、線程調度原理 在任意時刻&#xff0c;CPU只能執行一條指令&#xff0c;每個線程獲取到CPU的使用權之后才可以執行指令也就是說在任意時刻&#xff0c;只有一個線程占用CPU 處于運行狀態 多線程并發&#xff0c;實際上是指多個線程輪流獲取CPU 的使用權然后分別執行各自的任…

系統安全測試要怎么做?

進行系統安全測試時&#xff0c;可以按照以下詳細的步驟進行&#xff1a; 1、信息收集和分析&#xff1a; 收集系統的相關信息&#xff0c;包括架構、部署環境、使用的框架和技術等。 分析系統的安全需求、威脅模型和安全策略等文檔。 2、威脅建模和風險評估&#xff1a; 使…

調用被fishhook的原函數

OC類如果通過runtime被hook了&#xff0c;可以通過逆序遍歷方法列表的方式調用原方法。 那系統庫的C函數被fish hook了該怎么辦呢&#xff1f; 原理和OC類異曲同工&#xff0c;即通過系統函數dlopen()獲取動態庫&#xff0c;以動態庫為參數通過系統函數dlsym()即可獲取目標系統…