如果說程序可以簡單理解成“指令和數(shù)據(jù)的集合”蓝谨,那么你在任何平臺上編程都難以離開數(shù)據(jù)存儲矢沿,在Android平臺上自然也不會例外削樊。說到數(shù)據(jù)的存儲豁生,對于Key-Value對應的數(shù)據(jù)存取,Android提供SharedPreferences的方式可以進行方便的操作漫贞。大家也都覺得它的使用很簡單甸箱,但是有時候簡單的地方也會發(fā)生問題,而且你很難查覺到問題根源在這個地方绕辖。
面試題:修改SharedPreferences后兩種提交方式有什么區(qū)別摇肌?
SharedPreferences類是一個接口類,真正的實現(xiàn)類是SharedPreferencesImpl仪际。修改SharedPreferences需要獲取它的Editor,在對Editor進行put操作后昵骤,最后通過commit或者apply提交修改到內(nèi)存和文件树碱。當然有了兩種都可以提交的方法,肯定要區(qū)別一下的变秦。從實現(xiàn)類SharedPreferencesImpl的源碼上看也很容易看出兩者的區(qū)別:
commit這種方式很常用成榜,在比較早的SDK版本中就有了,這種提交修改的方式是同步的蹦玫,會阻塞調(diào)用它的線程赎婚,并且這個方法會返回boolean值告知保存是否成功(如果不成功刘绣,可以做一些補救措施)。
而apply是異步的提交方式挣输,目前Android Studio也會提示大家使用這種方式纬凤。
還有一點用得比較少的,就是SharedPreferences還提供一個監(jiān)聽接口可以監(jiān)聽SharedPreferences的鍵值變化撩嚼,需要監(jiān)控鍵值變化的可以用registerOnSharedPreferenceChangeListener添加監(jiān)聽器停士。
public interface SharedPreferences {
/**
* Interface definition for a callback to be invoked when a shared
* preference is changed.
*/
public interface OnSharedPreferenceChangeListener {
void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
}
多進程操作和讀取SharedPreferences的問題
前段時間,項目組里發(fā)現(xiàn)一個偶現(xiàn)的問題完丽,從Http明明獲取了正確的數(shù)據(jù)保存到SharedPreferences恋技,但立即再從SharedPreferences讀取這個值時發(fā)現(xiàn)是初始值。開始大家一直把精力放在Http的請求上逻族,最后才發(fā)現(xiàn)是SharedPreferences多進程間數(shù)據(jù)共享會導致的問題蜻底。
在SDK 3.0及以上版本,可以通過Context.MODE_MULTI_PROCESS屬性來實現(xiàn)SharedPreferences多進程共享聘鳞。如下設置:
public static SharedPreferences getSharedPreferences(String name) {
if (null != context) {
if (Build.VERSION.SDK_INT >= 11) {
return context.getSharedPreferences(name, Context.MODE_MULTI_PROCESS);
} else {
return context.getSharedPreferences(name, Context.MODE_PRIVATE);
}
}
return null;
}
本來以為通過MODE_MULTI_PROCESS屬性使用SharedPreferences就可以實現(xiàn)不同時程間共享數(shù)據(jù)薄辅,但是在真正使用中確發(fā)現(xiàn)有會有一定概率出現(xiàn)這個取值出錯(變?yōu)槌跏贾担﹩栴}。
最后發(fā)現(xiàn)在官網(wǎng)上Google也在SDK 6.0的版本將這個MODE_MULTI_PROCESS標識為deprecated(不贊成使用)搁痛。目前來說长搀,越來越多的項目在不斷的膨脹,為了降低單個進程的內(nèi)存占用率鸡典,使用"android:process"配置一些組件在單獨的進程中運行已經(jīng)是司空見慣了源请,所以大家在遇到自己的項目有多進程時,要注意一下SharedPreferences的問題彻况。
小結
在一個進程中谁尸,SharedPreference往往建單個實例就可以了,一般不會出現(xiàn)并發(fā)沖突纽甘,如果對提交的結果不關心的話良蛮,建議使用apply,當然需要確保提交成功且有后續(xù)操作的話悍赢,還是需要用commit的决瞳。
因為SharedPreferences在多進程方面的問題,大家也可以思考下能不能自己實現(xiàn)一個加強版的SharedPreferences解決這些問題左权,網(wǎng)上也有一些開源的替代方案皮胡,如Github上的tray。(建議大家先想一下赏迟,再看這個項目屡贺。)