在應用程式間及與使用者的通訊互動過程中,會產生並傳遞一系列資料。針對這些資料,有部分是隻在應用程式中使用的快取資料,還有一部分是在不同位置多次或長時間使用的持久化資料。
對於快取資料來說,通常以程式碼中定義區域性變數或全域性變數的方式訪問使用,這種使用方式伴隨在程式設計的整個過程中;而持久化資料,則需要以特定的檔案格式儲存在系統硬碟中,使用系統提供的框架方法來訪問使用。而根據要持久化儲存資料的複雜程度不同,分別有輕量級SharedPreferences
,資料庫SQLiteOpenHelper
或其封裝的Room
,以及二進位制訪問的檔案File
這三種方式。本文主要對持久化資料的幾種不同型別簡做介紹。
輕量級SharedPreferences
對於輕量級的鍵值對資料,可以使用android.content.SharedPreferences共享選項介面實現的相關類以持久化儲存。
以SharedPreferences
形式儲存的資料,將會以 key-value 鍵值對的形式,基於 xml 格式的檔案儲存在當前應用的內部儲存空間中。這種應用程式的內部儲存空間中的檔案,只允許其所屬應用程式讀寫。而當應用程式解除安裝後,或通過 系統桌面 - 設定 - 應用管理 - 當前應用程式 - 應用資料 - 清除資料 系列操作後,其內部儲存空間也將被清空。這在一定程度上保證了內部儲存空間的資料安全。
建立檔案
在AndroidSDK中已經定義SharedPreferencesImpl
類作為SharedPreferences
介面的實現類。
對於SharedPreferences
介面的例項化物件,在可以訪問上下文環境Context
物件的地方,可通過呼叫Context
物件的getSharedPreferences(String name, int mode)
方法獲取。其對應的 xml 格式檔案將在當前應用程式整個生命週期過程中讀寫訪問。
或者也可以在Activity
介面中,呼叫Activity
物件的getPreferences(int mode)
方法獲取,其對應的 xml 檔案只在當前介面生命週期中讀寫訪問。
在getSharedPreferences(String name, int mode)
方法中,
引數 name 指定儲存當前資料的 xml 格式檔案的檔名,其值可由開發者定義。
引數 mode 為檔案的開啟方式,其值通常為僅允許當前應用程式訪問該檔案的Context.MODE_PRIVATE=0
;在Android6.0即API23之前,該值也可以為允許多程序讀寫同步的Context.MODE_MULTI_PROCESS=4
,然而該模式下會出現各種異常問題,故此版本後被棄用;在Android4.2即API17之前,mode 值也可以為允許其他應用程式讀該檔案的Context.MODE_WORLD_READABLE=1
,和允許其他應用程式寫該檔案的Context.MODE_WORLD_WRITEABLE=2
,但這兩個值均不能保證當前應用程式的資料安全性,故此版本之後被棄用。
另外,如果看不慣系統定義的SharedPreferencesImpl
實現類,開發時完全可以自定義一個SharedPreferences
介面的實現類,在使用context.getSharedPreferences(String name, int mode)
獲取例項化物件的位置替換為自定義的實現類物件即可。
總之,在獲取SharedPreferences
物件時,系統檢測當前應用程式內部儲存空間中是否有指定 name 的 xml 格式檔案,若沒有將會先建立。之後系統便會開啟該檔案,通過SharedPreferences
物件就可以讀寫該檔案了。
資料寫入檔案
如果想向建立的SharedPreferences
物件所在檔案中寫入資料,只需要呼叫該物件的edit()
方法,以獲取android.content.SharedPreferences.Editor介面型別的物件。
類似於介面間互動使用的Intent
意圖中傳遞的資料方式,在SharedPreferences.Editor
介面物件中,可以使用putBoolean(String key, boolean value)
設定boolean
型別的資料,putFloat(String key, float value)
設定float
型別的資料,putStringSet(String key, Set<String> values)
設定String
集合的資料等。這一系列的設定方法,其引數一 key 都是作為SharedPreferences
檔案中唯一的String
型別的值,以標記當前資料;其引數二 value 則是要持久化儲存的資料值。
另外,在SharedPreferences.Editor
介面物件中,也可以使用remove (String key)
方法以刪除存在的引數 key 所標記的資料內容。或者直接使用clear()
方法清空設定的所有資料內容。
在通過SharedPreferences.Editor
介面物件設定或刪除完資料後,呼叫其apply()
或commit()
方法以一次性提交設定的所有資料,在提交之後系統會將上文設定的資料都儲存到SharedPreferences
檔案中。
雖然
commit()
方法可以返回boolean
值以判斷是否提交成功,但並不推薦使用該方法;使用apply()
方法可以更安全的保證提交的資料成功儲存。
檔案讀取資料
如果想讀取SharedPreferences
物件所在檔案的資料,就沒有將資料寫入檔案那麼繁瑣的步驟了。只需要直接呼叫SharedPreferences
物件的getBoolean(String key, boolean defValue)
獲取boolean
型別的資料值,getFloat(String key, float defValue)
獲取float
型別的資料值,getStringSet(String key, Set<String> defValues)
獲取Set<String>
型別的資料值等。這一系列的獲取方法,其引數一 key 與寫入檔案時的設定方法中的引數 key 一致,以標記響應資料;引數二 defaultValue 則是預設的資料值,當SharedPreferences
檔案中並沒有儲存引數 key 對應的資料時,將會返回 defaultValue 所設定的數值。
如果儲存的資料量並不多,也可以直接呼叫SharedPreferences
物件的getAll()
方法,獲取Map<String, ?>
集合型別的所有資料,再對得到的資料分別操作處理。
另外SharedPreferences
物件的contains(String key)
方法,也可以只判斷當前SharedPreferences
物件所在檔案中是否有引數 key 所標記的資料內容,返回boolean
型別的結果。
檔案修改的實時監聽
可以用SharedPreferences
物件的registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener)
方法,實時監聽當前SharedPreferences
檔案的修改操作。
引數 listener 是android.content.SharedPreferences.OnSharedPreferenceChangeListener介面的例項化物件,在該介面中實現了onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
方法。
一旦 listener 被註冊,在引數 sharedPreferences 對應的檔案中資料標記的 key 在被修改後, listener 中的onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
方法將會被系統回撥。
對於已經註冊的 listener ,尤其記得要在不需要監聽之後,呼叫SharedPreferences
物件的unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener)
,將之前註冊的OnSharedPreferenceChangeListener
物件撤銷掉,以防止在後續出現記憶體洩漏的問題。
輕量級的SharedPreferences
儲存方式,可以很方便的儲存一些簡單資料,其記憶體效率是比較高的。然而如果應用程式中所有的資料都使用這種儲存方式,反而使SharedPreferences
檔案的操作效率降低了,而且所有資料都使用這種鍵值對的形式存取,也會增加程式碼量。那麼有什麼更合適的儲存方式適合不同型別的資料嗎?詳情請關注下一篇文章。