Android 之 SharedPreferences 內(nèi)部原理淺析

Sharedpreferences 內(nèi)部工作原理:

  1. 調(diào)用getSharedPreferences(); 創(chuàng)建一個(gè)SharedPreferences對(duì)象,其中會(huì)先判斷是否存在對(duì)應(yīng)xml文件败明,如果發(fā)現(xiàn)存在則會(huì)有一個(gè)預(yù)加載操作钟鸵,這個(gè)操作是把xml文件的內(nèi)容通過(guò)I/O操作和XmlUitl 解析后存入一個(gè)map對(duì)象仲吏,所以我們調(diào)用SharedPreferences::getString();等get操作實(shí)際上是不會(huì)對(duì)文件做I/O操作,而是直接訪問(wèn)剛剛的map集合的內(nèi)容肘习,這提高了效率近零,如果對(duì)應(yīng)的xml不存在則重新創(chuàng)建一個(gè)對(duì)應(yīng)的xml文件珠洗。
@Override
public SharedPreferences getSharedPreferences(String name,int mode){
          SharedPreferences sp;
          //...
          sp=packagePrefs.get(name);
          if(sp==null){
              File prefsFile=getSharedPrefsFile(name);
              //該構(gòu)造方法會(huì)調(diào)用startLoadFromDisk();把數(shù)據(jù)從硬盤加載到內(nèi)存
            sp =new SharedPreferencesImpl(prefsFile,mode);
            packagePrefs.put(name,sp);
            //...
          return sp;
        }
}
  1. put寫操作:寫操作也有兩步溜歪,一是把數(shù)據(jù)先寫入內(nèi)存中,即map集合许蓖,二是把數(shù)據(jù)寫入硬盤文件中痹愚。這樣才能保證數(shù)據(jù)的完整性,寫操作有兩個(gè)提交的方式:
    commit():線程安全蛔糯,性能慢拯腮,一般來(lái)說(shuō)在當(dāng)前線程完成寫文件操作。
    apply(): 線程不安全蚁飒,性能高动壤,異步處理IO操作,一定會(huì)把這個(gè)寫文件操作放入一個(gè) SingleThreadExecutor 線程池中處理
  2. SharedPreferences 在第一次創(chuàng)建后會(huì)一直維持一個(gè)Singleton淮逻, 每次調(diào)用getSharedPreferences()都返回唯一的一個(gè)實(shí)例
SharedPreferences a=getSharedPreferences("test",0);
SharedPreferences b=getSharedPreferences("test",0);
SharedPreferences c=getSharedPreferences("test",0);
Log.i(TAG,"result:"+(a==b)+","+(b==c));
//9-10 09:15:17.810 2287-2287/com.xing.mayapplication l/MainActivity: result:true,true

SharedPreferences 使用封裝:

由于SharedPreferences的key 與 value 其實(shí)最終都是以String類型存在琼懊,所以可以這樣寫一個(gè)SharedPreferences工具類:

/**
* SharedPreferences工具
*/
public class PerferenceManager{
      private static final String PERF_NAME="com.xing_util.perf";
      private static final int CURRENT_VERSION_CODE=1;
      private volatile static PerferenceManager instance;
      private final SharedPreferences preferences;

      private PreferenceManager(Context context){
                  preferences=context.getSharedPreferences(PERF_NAME,Context.MODE_PRIVATE);
                  checkPrefVersion();
      }

      public static PerferenceManager getInstance(Context context){
                if(instance==null){
                  synchronized(PerferenceManager.class){
                          if(instance==null)
                            instance=new PerferenceManager(context);
                   }
                }
                return instance;
      }
       public final void putValue(String key,String value){
              preferences.edit().putString(key,value).apply();
       }
       public final String getValue(String key){
              checkIsLegal(key);
            return preferences.getString(key,"");
       }
       public final void deleteValue(String key){
             checkIsLegal(key);
            preferences.edit().remove(key).apply();
        }
        public final void clear(){
          preferences.edit().clear().apply();
        }
        private void checkIsLegal(String key){
              if(TextUtils.isEmpty(key))
                        throw new IllegalArgumentException("this parameter is illegal,key:"+key);
         }

        private void checkPrefVersion(){
            final int oldVersion=preferences.getInt(PERF_NAME,0);
            if (oldVersion<CURRENT_VERSION_CODE){
                preferences.edit()
                           .clear()
                           .putInt(PERF_NAME,CURRENT_VERSION_CODE).apply();
        }
    }
}

由于應(yīng)用版本升級(jí)時(shí)并不會(huì)刪除SharedPreferences文件阁簸,所以可以加個(gè)版本判斷,來(lái)進(jìn)行一些數(shù)據(jù)更新哼丈,從上面看來(lái)启妹,由于每次調(diào)用getSharedPreferences()都會(huì)有IO操作,當(dāng)內(nèi)容比較多時(shí)醉旦,那么就不適宜在Application 的onCreate 中進(jìn)行SharedPreferences 文件初始化了饶米,最好的辦法是開個(gè)子線程去完成它的創(chuàng)建和數(shù)據(jù)的預(yù)加載!3岛檬输!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匈棘,隨后出現(xiàn)的幾起案子丧慈,更是在濱河造成了極大的恐慌,老刑警劉巖主卫,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逃默,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡簇搅,警方通過(guò)查閱死者的電腦和手機(jī)完域,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)馍资,“玉大人,你說(shuō)我怎么就攤上這事关噪∧裥罚” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵使兔,是天一觀的道長(zhǎng)建钥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)虐沥,這世上最難降的妖魔是什么熊经? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮欲险,結(jié)果婚禮上镐依,老公的妹妹穿的比我還像新娘。我一直安慰自己天试,他們只是感情好槐壳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喜每,像睡著了一般务唐。 火紅的嫁衣襯著肌膚如雪雳攘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天枫笛,我揣著相機(jī)與錄音吨灭,去河邊找鬼。 笑死刑巧,一個(gè)胖子當(dāng)著我的面吹牛喧兄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播海诲,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼繁莹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了特幔?” 一聲冷哼從身側(cè)響起咨演,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚯斯,沒(méi)想到半個(gè)月后薄风,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拍嵌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年遭赂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片横辆。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撇他,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出狈蚤,到底是詐尸還是另有隱情困肩,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布脆侮,位于F島的核電站锌畸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏靖避。R本人自食惡果不足惜潭枣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幻捏。 院中可真熱鬧盆犁,春花似錦、人聲如沸篡九。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至翰铡,卻和暖如春钝域,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锭魔。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工例证, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迷捧。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓织咧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親漠秋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笙蒙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容