Android 持久化存儲原理與使用解析

一、核心存儲方案詳解
1.?SharedPreferences (SP)

使用方式:

// 獲取實例
SharedPreferences sp = getSharedPreferences("user_prefs", MODE_PRIVATE);// 寫入數據
sp.edit().putString("username", "john_doe").putInt("login_count", 5).apply(); // 異步提交// 讀取數據
String username = sp.getString("username", "default");
int loginCount = sp.getInt("login_count", 0);

原理流程:

優點:

  • 簡單易用,Android 原生支持

  • 適合存儲小量鍵值對數據

缺點:

  • ???全量寫入:修改單個值也重寫整個文件

  • ???ANR 風險apply()?異步提交在生命周期回調時可能阻塞主線程

  • ??多進程不安全MODE_MULTI_PROCESS?已廢棄

  • ??無類型安全:讀取時需手動轉換類型

使用場景:
低頻修改的簡單配置(如用戶主題設置、功能開關)


2.?MMKV(微信開源)

使用方式:

// build.gradle
implementation 'com.tencent:mmkv:1.3.0'
// 初始化
String rootDir = MMKV.initialize(this);// 獲取實例
MMKV kv = MMKV.defaultMMKV();// 寫入數據
kv.encode("session_token", "a1b2c3d4");
kv.encode("user_points", 1500);// 讀取數據
String token = kv.decodeString("session_token");
int points = kv.decodeInt("user_points");

原理流程:

優點:

  • ??高性能:讀寫速度比SP快100倍+

  • 🔒?多進程支持:完善的文件鎖機制

  • 📦?高效存儲:Protobuf編碼節省50%空間

  • 🔐?加密支持:AES加密敏感數據

缺點:

  • ? 需引入三方庫

  • ?? 數據模型較簡單(適合鍵值對)

使用場景:
高頻讀寫數據(如用戶積分)、多進程共享配置、替代SP的所有場景


3.?DataStore(Google官方)

使用方式(Preferences DataStore):

// build.gradle
implementation "androidx.datastore:datastore-preferences:1.0.0"
// 定義Key
val USER_NAME = stringPreferencesKey("user_name")
val LOGIN_COUNT = intPreferencesKey("login_count")// 創建DataStore
val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings")// 寫入數據
suspend fun saveData(name: String, count: Int) {dataStore.edit { preferences ->preferences[USER_NAME] = namepreferences[LOGIN_COUNT] = count}
}// 讀取數據
val userNameFlow: Flow<String> = dataStore.data.map { preferences -> preferences[USER_NAME] ?: "" }

Proto DataStore(類型安全):

// user_prefs.proto
message UserPrefs {string name = 1;int32 login_count = 2;bool is_premium = 3;
}
val Context.userPrefsStore: DataStore<UserPrefs> by dataStore(fileName = "user_prefs.pb",serializer = UserPrefsSerializer
)// 直接操作對象
viewModelScope.launch {context.userPrefsStore.updateData { prefs ->prefs.toBuilder().setLoginCount(10).build()}
}

優點:

  • 🛡??類型安全:Protobuf 編譯時校驗

  • ??異步操作:基于協程,無主線程阻塞風險

  • 🔄?數據流支持:響應式數據更新

  • 🔄?平滑遷移:提供SP遷移工具

缺點:

  • 📚 學習曲線較陡峭(需掌握協程/Protobuf)

  • 🚫 不支持多進程

使用場景:
新項目開發、復雜數據模型存儲、響應式配置更新


二、Intent 數據傳輸限制

使用方式:

// 傳遞數據
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("user_id", 12345);
intent.putExtra("document", pdfByteArray); // 危險操作!
startActivity(intent);// 接收數據
int userId = getIntent().getIntExtra("user_id", 0);
byte[] pdfData = getIntent().getByteArrayExtra("document");

限制原因:

為什么只能傳少量數據?

  1. Binder 限制:IPC傳輸緩沖區固定為?1MB(Android 8.0+ 部分設備2MB)

  2. 性能問題:大數據序列化/反序列化消耗CPU和內存

  3. 穩定性風險:可能引發OOM或ANR

  4. 生命周期不匹配:Activity可能被銷毀重建,丟失數據

解決方案:

數據大小推薦方案示例
< 100KB直接Intent傳遞intent.putExtra("id", 123)
100KB ~ 1MBFileProvider共享文件傳遞content:// URI
> 1MB持久化存儲+標識傳遞數據庫ID/文件路徑
復雜對象Parcelable序列化實現Parcelable接口

三、方案對比與選型指南

維度SharedPreferencesMMKVDataStoreIntent
存儲類型鍵值對鍵值對鍵值對/Protobuf對象臨時數據
性能極高
線程安全主線程風險安全安全(協程)主線程安全
多進程????(IPC)
ANR風險高(大數據)
數據大小<1MB無限制無限制<1MB
推薦場景低頻配置項高頻讀寫/多進程新項目/類型安全小數據傳遞

四、常見問題總結

Q1:SharedPreferences有什么缺陷?如何優化?

A:
主要缺陷:

  1. 全量寫入導致I/O性能差

  2. apply()異步提交可能引發ANR(ActivityThread等待QueuedWork)

  3. 多進程不安全(MODE_MULTI_PROCESS已廢棄)

  4. 無類型安全檢查

優化方案:

  1. 遷移到MMKV或DataStore

  2. 避免存儲超過1MB數據

  3. 對高頻修改項單獨拆分文件

Q2:MMKV為什么比SharedPreferences快?

A:
MMKV通過三重優化實現高性能:

  1. mmap內存映射:文件直連內存,省去系統調用和數據拷貝

  2. Protobuf編碼:比XML節省50%+存儲空間

  3. 增量更新:只追加修改數據,避免全文件重寫

  4. 多進程鎖:通過文件鎖實現安全并發訪問

Q3:DataStore相比SP的核心優勢?

A:
DataStore的四大優勢:

  1. 無ANR設計:協程異步API徹底避免主線程阻塞

  2. 類型安全:Proto DataStore支持編譯時類型檢查

  3. 響應式編程:通過Flow實現數據變更監聽

  4. 事務支持edit{}塊內操作保證原子性

Q4:Intent為什么不能傳大數據?

A:
Intent傳輸受限于三點:

  1. Binder IPC限制:傳輸緩沖區固定1-2MB

  2. 序列化開銷:大數據序列化消耗CPU/內存,可能導致ANR

  3. 生命周期風險:Activity重建時系統可能丟棄Intent數據

解決方案:

  • <1MB:直接使用Intent

  • 1-10MB:通過FileProvider傳遞URI

  • 10MB:持久化存儲后傳遞標識符


五、場景選擇


六、高頻問題總結

  1. SP的apply()commit()區別?

    apply()異步提交但不返回結果,commit()同步提交并返回boolean結果。注意apply()可能導致ANR。

  2. MMKV如何保證多進程安全?

    通過fcntl文件鎖實現寫互斥,跨進程場景使用pthread_mutex(需處理robust屬性)。

  3. DataStore如何從SP遷移?

    val dataStore = createDataStore(preferencesMigration = SharedPreferencesMigration(context, "sp_name"))

  4. Intent傳遞大Bitmap的正確方式?

    // 步驟1:保存到文件
    File file = saveBitmapToCache(bitmap); // 步驟2:通過FileProvider生成URI
    Uri uri = FileProvider.getUriForFile(context, "com.example.provider", file);// 步驟3:傳遞URI并設置權限
    intent.putExtra("image_uri", uri);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  5. 為什么推薦用FileProvider不用絕對路徑?

    FileProvider提供臨時權限控制,避免直接暴露文件路徑的安全風險

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

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

相關文章

無 sudo 權限的環境下將 nvcc (CUDA Toolkit) 安裝到個人目錄 linux

要在無 sudo 權限的環境下將 nvcc 安裝到 home 個人目錄&#xff0c;你可以手動安裝 CUDA Toolkit 到你的 $HOME 目錄&#xff0c;只需以下幾步即可使用 nvcc 編譯 CUDA 程序。 ? 步驟&#xff1a;本地安裝 CUDA Toolkit&#xff08;含 nvcc&#xff09; 下載 CUDA Toolkit Ru…

從指標定義到AI執行流:衡石SENSE 6.0的BI PaaS如何重構ISV分析鏈路

一、痛點&#xff1a;ISV行業解決方案的“三重斷鏈”傳統ISV構建行業分析模塊時面臨的核心挑戰&#xff1a;指標定義碎片化&#xff1a;客戶A的“銷售額”含稅&#xff0c;客戶B不含稅&#xff0c;衍生指標無法復用&#xff1b;分析-執行割裂&#xff1a;發現庫存異常后需人工導…

構建跨平臺遠程醫療系統中的視頻通路技術方案探究

一、遠程醫療走向日常化&#xff0c;音視頻能力成為關鍵基礎設施 隨著醫療數字化與分級診療體系的不斷演進&#xff0c;遠程醫療正從試點探索階段&#xff0c;逐步邁向常態化、標準化應用。從縣域醫院遠程問診、基層醫療協作&#xff0c;到大型三甲醫院的術中協同、專科教學直…

Blackbox Exporter Docker 安裝配置,并與 Prometheus 集成

1. 創建配置文件目錄bashmkdir -p ~/docker/blackbox/config cd ~/docker/blackbox2. 創建 Blackbox Exporter 配置文件 config/blackbox.ymlyamlmodules:http_2xx: # HTTP 可用性檢測(響應 2xx/3xx 狀態碼)prober: httphttp:valid_http_versions: ["HTTP/1.1", &qu…

杰理通用MCU串口+AT指令+485通訊工業語音芯片

一、概述 在現代智能設備與自動化系統中&#xff0c;語音交互功能日益普及&#xff0c;通用 MCU 語音芯片作為核心組件&#xff0c;承擔著關鍵的語音處理任務。其強大的功能不僅體現在語音合成、識別等方面&#xff0c;還包括高效的通信能力。串口 AT 指令 485 通訊模式為通用…

Krpano 工具如何調節全景圖片切割之后的分辨率

文章目錄概要第一步1.1 復制一下這個文件中的key &#xff0c;打開 krpano Tools.exe第二步 修改切片之后的分辨率修改前的效果修改后的效果概要 前端渲染全景圖模擬3D場景 Krpano 工具 獲取到后的默認圖片分辨率是2048*2048的&#xff0c;如果覺得分辨率低了可以自行在工具中…

物聯網十大應用領域深度解析

一、智能物流技術基礎&#xff1a;RFID、無線傳感器網絡、互聯網與運籌學、供應鏈管理理論結合 應用場景&#xff1a;倉儲管理&#xff1a;RFID標簽實現庫存實時監控&#xff0c;自動補貨系統降低缺貨率。配送優化&#xff1a;通過GPS與物聯網數據分析規劃最優路徑&#xff0c;…

ElasticSearch基礎數據查詢和管理詳解

目錄 一、 ElasticSearch核心概念 1. 全文搜索&#xff08;Full-Text Search&#xff09; 2. 倒排索引&#xff08;Inverted Index&#xff09; 3. ElasticSearch常用術語 3.1 映射&#xff08;Mapping&#xff09; 3.2 索引&#xff08;Index&#xff09; 3.3 文檔&…

SSE與Websocket有什么區別?

SSE&#xff08;Server-Sent Events&#xff09;和WebSocket都能實現服務器與客戶端的實時通信&#xff0c;但它們在協議設計、應用場景和技術特性上有明顯差異。以下從多個維度對比兩者的區別&#xff1a; 1. 協議基礎 SSE 基于HTTP協議&#xff0c;是HTTP的擴展。使用單向通…

力扣Hot100疑難雜癥匯總

寫在前面 這一篇博客主要用來記錄力扣Hot100中我反復刷&#xff0c;但又反復錯的難題&#xff0c;為了防止秋招手撕的時候尬住&#xff0c;寫這篇博客記錄一下那些容易遺忘而且對我來說難度較大的題目。后面復習的時候重點對著這個名單來刷題。 二叉樹部分 114. 二叉樹展開為…

硬核接線圖+配置步驟:遠程IO模塊接入PLC全流程詳解

遠程IO模塊和PLC&#xff08;可編程邏輯控制器&#xff09;的連接涉及多個方面&#xff0c;包括硬件準備、軟件配置、接線方法以及注意事項等。PLC品牌大多分為國產、歐系、美系、日系。國產PLC主要有匯川、臺達、和利時、信捷等品牌&#xff1b;歐美系PLC以西門子、施耐德、羅…

【數據結構】長幼有序:樹、二叉樹、堆與TOP-K問題的層次解析(含源碼)

為什么我們要學那么多的數據結構&#xff1f;這是因為沒有一種數據結構能夠去應對所有場景。我們在不同的場景需要選擇不同的數據結構&#xff0c;所以數據結構沒有好壞之分&#xff0c;而評估數據結構的好壞要針對場景&#xff0c;就如我們已經學習的結構而言&#xff0c;如果…

wps dispimg python 解析實現參考

在 wps excel 中&#xff0c;可以把圖片嵌入單元格&#xff0c;此時會圖片單元格會顯示如下內容 DISPIMG("ID_142D0E21999C4D899C0723FF7FA4A9DD",1)下面是針對這中圖片文件的解析實現 參考博客&#xff1a;Python讀取wps中的DISPIMG圖片格式_wps dispimg-CSDN博客:h…

Java學習---Spring及其衍生(下)

接下來就到了Spring的另外2個知名的衍生框架&#xff0c;SpringBoot和SpringCloud。其中&#xff0c;SpringBoot 是由 Pivotal 團隊開發的一個基于 Spring 的框架&#xff0c;它的設計目的是簡化 Spring 應用程序的初始搭建和開發過程。SpringBoot 遵循 “約定優于配置” 的原則…

殘月頭像閣

殘月頭像閣 使用說明: 直接上傳服務器即可## 項目簡介殘月頭像閣是一個簡潔美觀的頭像網站開源程序 支持快速部署與自定義采用擬態(Neumorphism)設計風格&#xff0c;提供多種分類的頭像## 功能特性- &#x1f5bc;? 多分類頭像展示&#xff08;男生、女生、卡通、情侶、動漫&…

文獻綜述AI生成免費工具推薦:高效整理文獻

做學術研究時&#xff0c;文獻綜述無疑是讓很多學子和科研工作者頭疼的環節。查閱、篩選、梳理大量文獻&#xff0c;然后進行歸納總結&#xff0c;最終形成一篇條理清晰的文獻綜述&#xff0c;這一整個過程常常耗費數日甚至數周。而面對課業壓力與緊迫的論文截止時間&#xff0…

OpenCV —— contours_matrix_()_[]

&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?Take your time ! &#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?&#x1f636;?&#x1f32b;?…

android 小bug :文件沖突的問題

文章目錄前言1、問題&#xff1a;兩個文件沖突了2、原因&#xff1a;3、結果&#xff1a;后語前言 一個身份證模塊識別的小bug&#xff0c;記錄一下&#xff0c;這應該是第三次出現&#xff0c;每次出現都不太記得&#xff0c;還是得記錄&#xff0c;不然都是重復檢索的過程。…

Java學習第七十三部分——Redis

目錄 一、前言提要 二、核心特性 三、數據結構 四、應用場景 五、架構模式 六、性能優勢 七、客戶端庫 八、注意事項 九、選擇建議 十、使用示例——基于Jedis 和 Lettuce 十一、生態集成——基于Spring Boot 十二、企業級能力 十三、持久化機制 十四、高…

(LeetCode 每日一題) 3487. 刪除后的最大子數組元素和 (哈希表)

題目&#xff1a;3487. 刪除后的最大子數組元素和 思路&#xff1a;哈希表&#xff0c;時間復雜度0(n)。 維護數組nums的最大值mx&#xff0c;同時用哈希表mp維護數組中非負數出現的情況&#xff0c;記錄非負數的和sum。如果哈希表mp的大小為0&#xff0c;那么數組nums都是負數…