1.原理和概述
- 1.儲存於硬盤上的xml鍵值對。
- 2.輕量級數據儲存,數據多了容易引發性能問題
- 3.xml文件所在目錄位於/data/data//shared_prefs/,能夠有多個文件。
2.初始化
- 1.ContextImpl記錄着SharedPreferences的重要數據
- 1.sSharedPrefsCache:以包名爲key, 二級key是以SP文件, 以SharedPreferencesImpl爲value的嵌套map結構. 這裏須要sSharedPrefsCache是靜態類成員變量, 每一個進程是保存惟一一份, 且由ContextImpl.class鎖保護.
- 2.mSharedPrefsPaths:記錄全部的SP文件, 以文件名爲key, 具體文件爲value的map結構
- 3.mPreferencesDir:是指SP所在目錄, 是指/data/data//shared_prefs/
- 2.Context.getSharedPreferences(name, mode)獲取SharedPreferences,只要是Context都能獲取
- 1.先從mSharedPrefsPaths查詢是否存在相應文
- 2.若是文件不存在, 則建立新的xml文件; 若是目錄也不存在, 則先建立目錄建立目錄/data/data/package name/shared_prefs/
- 3.檢查mode
- 1.MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE 在android N開始就會拋出異常,防止外部應用讀寫該文件
- 2.MODE_MULTI_PROCESS 是多進程方式使用文件,因爲有內存緩存的緣故這種模式下不怎麼能保證進程安全,後續google再也不支持。代替的方式有ContentProvider。
- 4.建立同名的.bak備份文件用於發生異常時, 可經過備份文件來恢復數據.
- 5.將xml文件加載到內存中,這個操做的線程是新開的,可是會阻塞getXXX()和setxxx()以及edit()方法。
- 6.一旦徹底加載到內存, 後續的getXXX()則是直接訪問內存
3.讀取
- 1.在xml文件所有內加載到內存中以前,讀取操做是阻塞的
- 2.在xml文件所有內加載到內存中以後,是直接讀取內存中的數據
4.寫入
- 1.獲取一個Editor
- 2.putXXX的時候,只是將數據寫入到內存中的一個mModified Map中
- 3.執行commit 或 apply操做
- 1.commit:
- 1.將mModified的數據更新到SPI的mMap中
- 2.當沒有key發生改變, 則直接返回; 不然將mMap所有信息寫入文件, 若是寫入成功則刪除備份文件,若是寫入失敗則刪除mFile
- 3.每次commit是把所有數據更新到文件, 因此每一個文件的數據量必須保證足夠精簡
- 2.apply:
- 1.apply跟commit的最大區別 在於apply的寫入文件操做是在單線程的線程池來完成.而commit是在當前線程阻塞運行的。
- 2.apply方法開始的時候, 會把一個任務awaitCommit,放入一個任務隊列中QueuedWork
- 3.單線程池會不斷從QueuedWork取任務而後執行。
- QueuedWork在這裏存在的價值主要是用於在Stop Service, finish BroadcastReceiver過程用於 斷定是否處理完全部的異步SP操做.
- 4.總結
- 1.apply由於是異步的沒有返回值, commit是同步的有返回值能知道修改是否提交成功
- 2.多併發的提交commit時,需等待正在處理的commit數據更新到磁盤文件後纔會繼續往下執行,從而下降效率; 而apply只是原子更新到內存,後調用apply函數會直接覆蓋前面內存數據,從必定程度上提升不少效率。 3.edit()每次都是建立新的EditorImpl對象.
5.優化
- 1.sp裏面存儲特別大的key/value, 有助於減小卡頓/anr
- 2.不要高頻地使用apply和commit, 儘量地批量提交。由於每次提交就是xml文件的所有重寫
- 3.commit直接在主線程操做, 要注意
- 4.不要使用MODE_MULTI_PROCESS,多線程不該該使用SPI
- 5.高頻寫操做的key與高頻讀操做的key能夠適當地拆分文件, 因爲減小同步鎖競爭
- 6.不要一上來就執行getSharedPreferences().edit(),由於getSharedPreferences()是在其餘線程進行可是會阻塞.edit()。
- 7.不要連續屢次edit(), 應該獲取一次獲取edit(),而後屢次執行putxxx(), 減小內存波動。
參考文章:全面剖析SharedPreferencesandroid
不販賣焦慮,也不標題黨。分享一些這個世界上有意思的事情。題材包括且不限於:科幻、科學、科技、互聯網、程序員、計算機編程。下面是個人微信公衆號:世界上有意思的事,乾貨多多等你來看。 git