Android基礎知識之SharedPreferences知識點總結

1.SharedPreferences簡介

??Sharedpreferences是Android平臺上一個輕量級的存儲類道逗,可以用于保存應用程序的各種配置信息振乏,如應用設置里面的各種開關、是否打開音效嚎卫、是否使用震動效果拴疤、小游戲的玩家積分等,其本質是以“鍵-值”對的方式保存數(shù)據(jù)到本地的 xml 文件中依鸥,其文件保存在 /data/data/<package name>/shared_prefs 目錄下。
??核心原理:以“鍵-值”對的方式保存數(shù)據(jù)到本地的 xml 文件中畦徘,具體實現(xiàn)是在 SharedPreferencesImpl 里面使用Map來管理毕籽,xml 文件的具體保存路徑是在 /data/data/<package name>/shared_prefs 目錄下抬闯。SharedPreferences對象本身只能獲取數(shù)據(jù)而不支持存儲和修改井辆,存儲修改是通過SharedPreferences.edit()獲取的內部接口Editor對象實現(xiàn)。

??SharedPreferences本身是一 個接口溶握,程序無法直接創(chuàng)建SharedPreferences實例杯缺,只能通過Context提供的getSharedPreferences(String name, int mode)方法來獲取SharedPreferences實例,該方法中name表示要操作的xml文件名睡榆,第二個參數(shù)具體如下:

Context.MODE_APPEND: 追加方式存儲
Context.MODE_PRIVATE: 指定該SharedPreferences數(shù)據(jù)只能被本應用程序讀萍肆、寫。
Context.MODE_WORLD_READABLE:  指定該SharedPreferences數(shù)據(jù)能被其他應用程序讀胀屿,但不能寫塘揣。
Context.MODE_WORLD_WRITEABLE:  指定該SharedPreferences數(shù)據(jù)能被其他應用程序讀,寫
Context.MODE_MULTI_PROCESS: 適用于多進程訪問(目前已被廢棄宿崭,google官方推薦使用ContentProvider來實現(xiàn)進程間共享訪問)

Editor有如下主要重要方法:

SharedPreferences.Editor clear():清空SharedPreferences里所有數(shù)據(jù)
SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key對應的數(shù)據(jù)亲铡,其中xxx 可以是boolean,float,int等各種基本類型據(jù)
SharedPreferences.Editor remove(): 刪除SharedPreferences中指定key對應的數(shù)據(jù)項
boolean commit(): 當Editor編輯完成后,使用該方法提交修改

??首次創(chuàng)建SharedPreferences對象(即SharedPreferences初始化時)葡兑,會根據(jù)文件名將文件下內容一次性加載到mMap容器中奖蔓,每當我們edit都會創(chuàng)建一個新的EditorImpl對象,當修改或者添加數(shù)據(jù)時會將數(shù)據(jù)添加到mModifiled容器中讹堤,然后commit或者apply操作比較mMap與mModifiled數(shù)據(jù)修正mMap中最后一次提交數(shù)據(jù)然后寫入到文件中吆鹤。
??使用SharedPreferences的 get 方法獲取數(shù)據(jù)時是直接從 mMap 中讀取的,直接從 mMap 中讀取數(shù)據(jù)可以提高讀取的效率洲守,但也間接表明 SharedPreferences 不適合存放 大的key和value疑务,因為存放大的key和value在SharedPreferences中,數(shù)據(jù)會一直存儲在內存中得不到釋放占用較大的內存梗醇,容易引發(fā)系統(tǒng) GC暑始,嚴重時導致界面丟幀甚至ANR。

2.SharedPreferences提交數(shù)據(jù)的方法commit()婴削、apply()的區(qū)別及使用場景

commit()廊镜、apply()的區(qū)別

  • commit() 方法是Android API 1開始就存在的方法,而 apply() 方法是從Android API 9 開始增加的方法唉俗;
  • commit() 和 apply() 雖然都是原子性操作嗤朴,但是原子的操作范圍不同配椭,commit() 是原子提交到數(shù)據(jù)庫,從提交數(shù)據(jù)到存在Disk中都是同步過程雹姊;而 apply() 方法是原子提交到內存股缸,從內存到數(shù)據(jù)庫的更新是異步操作;
  • 提交相同的數(shù)據(jù) commit() 方法的效率會比apply() 方法提交的速度慢吱雏,即 apply()方法提交數(shù)據(jù)的效率較高敦姻;
  • apply() 沒有返回值,而 commit() 有返回值表明提交修改是否成功歧杏。

使用場景

??從 commit()和 apply() 兩個方法的區(qū)別中可以得出兩個方法的使用場景:在一個進程中镰惦,由于sharedPreference是單實例的,只要保證內存緩存正確就能保證運行時數(shù)據(jù)的正確性犬绒,一般不會出現(xiàn)并發(fā)沖突旺入,所以如果對提交結果不關心的話,建議使用apply()凯力,只有在關心提交結果的情況下使用 commit()茵瘾。

3.Sharedpreferences跨進程訪問問題

??對于多進程的應用,若在某一個進程獲取到的SP值不是最新的咐鹤,很可能是創(chuàng)建SP的時候指定的模式有問題拗秘,應該指定為多進程的模式:Context.MODE_MULTI_PROCESS,設置之后可以實時讀取Sharedpreferences中修改后的值祈惶。

??通過Context.MODE_MULTI_PROCESS屬性使用SharedPreferences雖然可以實現(xiàn)多進程訪問SharedPreferences數(shù)據(jù)的問題雕旨,但是這種方式的多進程共享數(shù)據(jù)可能會出現(xiàn)數(shù)據(jù)不一致的問題。問題原因是因為進程間是不能內存共享的行瑞,每個進程操作的SharedPreferences都是一個單獨的實例奸腺,SharedPreferences數(shù)據(jù)寫入的時機也不確定,而且不能通過加鎖解決多進程的數(shù)據(jù)同步血久,從而導致了多進程間通過SharedPreferences來共享數(shù)據(jù)是不安全的突照。

??結論:Context.MODE_MULTI_PROCESS這個屬性Google已經(jīng)廢棄,不建議使用了氧吐,對于多進程間的數(shù)據(jù)共享建議使用ContentProvider讹蘑。若要用Sharedpreferences實現(xiàn)多進程數(shù)據(jù)共享,只能在確保不會同時操作SharedPreferences數(shù)據(jù)的前提下使用筑舅,但這個條件很難保證座慰,所以建議最好不要使用。

4.訪問其他應用中的Preference

??如果要訪問其他應用中的Preference翠拣,必須滿足的條件是版仔,要訪問的應用的Preference創(chuàng)建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE權限。

??舉例,假如有個<package name>為com.alexlee1987.demo下面的應用使用了下面語句創(chuàng)建了Preference蛮粮,getSharedPreferences("demo", Context.MODE_WORLD_READABLE),現(xiàn)在要訪問該Preferences:

首先益缎,需要創(chuàng)建上面的Context,然后通過Context訪問Preferences然想,訪問preference時會在應用所在包下的shared_prefs目錄找到preference:

Context context = createPackageContext("com.alexlee1987.demo", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = context.getSharedPreferences("demo", Context.MODE_WORLD_READABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 0);

??如果不通過創(chuàng)建Context訪問其他應用的preference莺奔,可以以讀取xml文件方式直接訪問其他應用preference對應的xml文件,如:
File xmlFile = new File(“/data/data/<package name>/shared_prefs/itcast.xml”);//<package name>應替換成應用的包名变泄。

5.使用建議

??Sharedpreferences是Android平臺上一個輕量級的存儲類令哟,可以方便快捷的在本地保存應用的一些信息,Sharedpreferences好用妨蛹,但也不能濫用屏富,使用過程中建議遵循以下規(guī)則:

  1. 不要存放大的key和value在SharedPreferences中,數(shù)據(jù)一直存儲在內存中得不到釋放滑燃,內存使用過高會頻發(fā)引發(fā)GC役听,導致界面丟幀甚至ANR颓鲜;
  2. 不相關的配置選項最好不要放在一起表窘,單個文件越大讀取速度則越慢;
  3. 讀取頻繁的key和不頻繁的key盡量不要放在一起甜滨;
  4. commit發(fā)生在UI線程中乐严,apply發(fā)生在工作線程中,對于數(shù)據(jù)的提交最好是批量操作統(tǒng)一提交衣摩。雖然apply發(fā)生在工作線程(不會因為IO阻塞UI線程)但是如果添加任務較多昂验,Activity頁面退出時有可能會阻塞,嚴重時甚至會出現(xiàn)ANR艾扮,具體可以參照ActivityThread源碼中handleStopActivity方法實現(xiàn)既琴;


    handleStopActivity源碼
  5. 盡量不要存放json和html,這種可以直接文件緩存泡嘴;
  6. 最好提前初始化SharedPreferences甫恩,避免SharedPreferences第一次創(chuàng)建時讀取文件線程未結束而出現(xiàn)等待情況,可以考慮在Application初始化的時候初始化SharedPreferences酌予。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末磺箕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抛虫,更是在濱河造成了極大的恐慌松靡,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件建椰,死亡現(xiàn)場離奇詭異雕欺,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門屠列,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛛枚,“玉大人,你說我怎么就攤上這事脸哀”钠郑” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵撞蜂,是天一觀的道長盲镶。 經(jīng)常有香客問我,道長蝌诡,這世上最難降的妖魔是什么溉贿? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮浦旱,結果婚禮上宇色,老公的妹妹穿的比我還像新娘。我一直安慰自己颁湖,他們只是感情好宣蠕,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甥捺,像睡著了一般抢蚀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镰禾,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天皿曲,我揣著相機與錄音,去河邊找鬼吴侦。 笑死屋休,一個胖子當著我的面吹牛,可吹牛的內容都是我干的备韧。 我是一名探鬼主播劫樟,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼盯蝴!你這毒婦竟也來了毅哗?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捧挺,失蹤者是張志新(化名)和其女友劉穎虑绵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闽烙,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡翅睛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年声搁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捕发。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡疏旨,死狀恐怖,靈堂內的尸體忽然破棺而出扎酷,到底是詐尸還是另有隱情檐涝,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布法挨,位于F島的核電站谁榜,受9級特大地震影響,放射性物質發(fā)生泄漏凡纳。R本人自食惡果不足惜晚凿,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一氮发、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧结笨,春花似錦袍祖、人聲如沸颁井。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偏序,卻和暖如春页畦,著一層夾襖步出監(jiān)牢的瞬間胖替,已是汗流浹背研儒。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留独令,地道東北人端朵。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像燃箭,于是被迫代替她去往敵國和親冲呢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容