在應用程序間及與用戶的通信交互過程中,會產生並傳遞一系列數據。針對這些數據,有部分是只在應用程序中使用的緩存數據,還有一部分是在不同位置多次或長時間使用的持久化數據。
對於緩存數據來說,通常以代碼中定義局部變量或全局變量的方式訪問使用,這種使用方式伴隨在編程的整個過程中;而持久化數據,則需要以特定的文件格式保存在系統硬盤中,使用系統提供的框架方法來訪問使用。而根據要持久化保存數據的復雜程度不同,分別有輕量級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
文件的操作效率降低了,而且所有數據都使用這種鍵值對的形式存取,也會增加代碼量。那么有什么更合適的存儲方式適合不同類型的數據嗎?詳情請關注下一篇文章。