讀書筆記5-資料儲存篇

niknowzcd發表於2019-03-01

本系列博文 基於是前微信高階工程師張紹文專欄 《Android開發高手課》的讀書筆記。

文章所寫內容是本人讀完的感悟,需要原文的朋友請自行購買。

儲存優化篇

Android分割槽

分割槽簡單來說就是將裝置中的儲存劃分為一些互不重疊的部分,每個部分都可以單獨格式化,用作不同的目的。

  • /system: 作業系統預留,用來儲存系統檔案和框架的,系統升級和恢復時會擦除這一整塊分割槽
  • /data: 用來儲存使用者資料的地方,手機上恢復出廠設定的那個操作就只會擦除這部分資料
  • /cache: 系統升級或者恢復時的備用分割槽
  • /vendor: 用來存放手機廠商對Android系統的修改
  • /storge: 內建或者外接的sdcard

資料儲存需要考慮哪些要素

資料儲存就是把特定的資料結構轉化成可以被記錄和還原的格式,這個資料格式可以是二進位制的,也可以是 XML、JSON、Protocol Buffer 這些格式。

在選擇資料儲存的時候需要考慮的要素

讀書筆記5-資料儲存篇

資料儲存的選項

  • SharedPreferences
  • ContentProvider
  • 檔案
  • 資料庫

SharedPreferences

使用場景

用於儲存一些非常簡單,輕量的資料。

優點

  • 系統支援,使用簡單
  • 相容性強

缺點

  • 跨程式不安全
  • 載入緩慢。SharedPreferences 檔案的載入使用了非同步執行緒,而且載入執行緒並沒有設定執行緒優先順序,如果這個時候主執行緒讀取資料就需要等待檔案載入執行緒的結束
  • 全量寫入。無論是呼叫 commit() 還是 apply(),即使我們只改動其中的一個條目,都會把整個內容全部寫到檔案。而且即使我們多次寫入同一個檔案,SP 也沒有將多次修改合併為一次,這也是效能差的重要原因之一。

基於以上原因,各大公司都會有對應的一個替代的儲存方案,比如微信的MMKV

ContentProvider

使用場景

跨程式,跨應用程式之間的大資料量互動,總體來說ContentProvider的整體框架還是不錯的,目前市面上好像也沒有什麼自研的架構替代。

需要注意的點

ContentProvider 的生命週期預設在 Application onCreate() 之前,而且都是在主執行緒建立的。我們自定義的 ContentProvider 類的建構函式、靜態程式碼塊、onCreate 函式都儘量不要做耗時的操作,會拖慢啟動速度。

物件的序列化

Serializable

java原生的序列化機制,其本身是通過 ObjectInputStream 和 ObjectOutputStream 來實現的,由於在序列化過程中使用了大量的反射和臨時變數使得效能下降,檔案體積變大。

需要注意的點

  • 不被序列化的欄位。類的 static 變數以及被宣告為 transient 的欄位,預設的序列化機制都會忽略該欄位,不會進行序列化儲存。當然我們也可以使用進階的 writeReplace 和 readResolve 方法做自定義的序列化儲存。
  • serialVersionUID。在類實現了 Serializable 介面後,我們需要新增一個 Serial Version ID,它相當於類的版本號。這個 ID 我們可以顯式宣告也可以讓編譯器自己計算。通常我建議顯式宣告會更加穩妥,因為隱式宣告假如類發生了一點點變化,進行反序列化都會由於 serialVersionUID 改變而導致 InvalidClassException 異常。
  • 構造方法。Serializable 的反序列預設是不會執行建構函式的,它是根據資料流中對 Object 的描述資訊建立物件的。如果一些邏輯依賴建構函式,就可能會出現問題,例如一個靜態變數只在建構函式中賦值,當然我們也可以通過進階方法做自定義的反序列化修改。

Parcelable

主要解決Serializable效能低下的問題。

使用Parcelable比Serializable需要多新增一些自定義程式碼,正是因為這些程式碼,使得Parcelable在序列化的時候不需要採用大量反射這種耗時的行為,從而提高效能。

需要注意的點

使用Parcelable進行永久儲存的話,會存在一些問題。

  • 系統版本的相容性。由於 Parcelable 設計本意是在記憶體中使用的,我們無法保證所有 Android 版本的Parcel.cpp實現都完全一致。如果不同系統版本實現有所差異,或者有廠商修改了實現,可能會存在問題。
  • 資料前後相容性。Parcelable 並沒有版本管理的設計,如果我們類的版本出現升級,寫入的順序及欄位型別的相容都需要格外注意,這也帶來了很大的維護成本。

一般來說,如果需要持久化儲存的話,一般還是不得不選擇效能更差的 Serializable 方案。

Serial

Twitter開源的Serial保留了Serializable和Parcelable的大部分優點

讀書筆記5-資料儲存篇

資料的序列化

Serial 效能看起來還不錯,但是物件的序列化要記錄的資訊還是比較多,在操作比較頻繁的時候,對應用的影響還是不少的,這個時候我們可以選擇使用資料的序列化。

JSON

優點

  • 相比物件序列化方案,速度更快,體積更小。
  • 相比二進位制的序列化方案,結果可讀,易於排查問題。
  • 使用方便,支援跨平臺、跨語言,支援巢狀引用。

市面上可用的框架有Android自帶的JSON庫,Google的Gson,阿里的FastJson,美團的MSON

總的來說Gson的相容性最好,資料量極大時,FastJson的效能最佳。

Protocol Buffers

二進位制序列化方案,資料量龐大的時候效能優於JSON,

資料庫優化

推薦使用自帶的SQLite,Realm或者Google的LevelDB。

這部分內容在張老師文中提到的多是執行緒併發,索引優化,page和快取處理等。比較深,這裡就不提了。

相關文章