Android面試一天一題(14 Day:SharedPreferences)

如果說(shuō)程序可以簡(jiǎn)單理解成“指令和數(shù)據(jù)的集合”,那么你在任何平臺(tái)上編程都難以離開(kāi)數(shù)據(jù)存儲(chǔ),在Android平臺(tái)上自然也不會(huì)例外。說(shuō)到數(shù)據(jù)的存儲(chǔ),對(duì)于Key-Value對(duì)應(yīng)的數(shù)據(jù)存取,Android提供SharedPreferences的方式可以進(jìn)行方便的操作。大家也都覺(jué)得它的使用很簡(jiǎn)單,但是有時(shí)候簡(jiǎn)單的地方也會(huì)發(fā)生問(wèn)題,而且你很難查覺(jué)到問(wèn)題根源在這個(gè)地方。

面試題:修改SharedPreferences后兩種提交方式有什么區(qū)別?

SharedPreferences類是一個(gè)接口類,真正的實(shí)現(xiàn)類是SharedPreferencesImpl。修改SharedPreferences需要獲取它的Editor,在對(duì)Editor進(jìn)行put操作后,最后通過(guò)commit或者apply提交修改到內(nèi)存和文件。當(dāng)然有了兩種都可以提交的方法,肯定要區(qū)別一下的。從實(shí)現(xiàn)類SharedPreferencesImpl的源碼上看也很容易看出兩者的區(qū)別:

commit這種方式很常用,在比較早的SDK版本中就有了,這種提交修改的方式是同步的,會(huì)阻塞調(diào)用它的線程,并且這個(gè)方法會(huì)返回boolean值告知保存是否成功(如果不成功,可以做一些補(bǔ)救措施)。
而apply是異步的提交方式,目前Android Studio也會(huì)提示大家使用這種方式。

還有一點(diǎn)用得比較少的,就是SharedPreferences還提供一個(gè)監(jiān)聽(tīng)接口可以監(jiān)聽(tīng)SharedPreferences的鍵值變化,需要監(jiān)控鍵值變化的可以用registerOnSharedPreferenceChangeListener添加監(jiān)聽(tīng)器。

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);
    }

多進(jìn)程操作和讀取SharedPreferences的問(wèn)題

前段時(shí)間,項(xiàng)目組里發(fā)現(xiàn)一個(gè)偶現(xiàn)的問(wèn)題,從Http明明獲取了正確的數(shù)據(jù)保存到SharedPreferences,但立即再?gòu)腟haredPreferences讀取這個(gè)值時(shí)發(fā)現(xiàn)是初始值。開(kāi)始大家一直把精力放在Http的請(qǐng)求上,最后才發(fā)現(xiàn)是SharedPreferences多進(jìn)程間數(shù)據(jù)共享會(huì)導(dǎo)致的問(wèn)題。

在SDK 3.0及以上版本,可以通過(guò)Context.MODE_MULTI_PROCESS屬性來(lái)實(shí)現(xiàn)SharedPreferences多進(jìn)程共享。如下設(shè)置:

    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;
    }

本來(lái)以為通過(guò)MODE_MULTI_PROCESS屬性使用SharedPreferences就可以實(shí)現(xiàn)不同時(shí)程間共享數(shù)據(jù),但是在真正使用中確發(fā)現(xiàn)有會(huì)有一定概率出現(xiàn)這個(gè)取值出錯(cuò)(變?yōu)槌跏贾担﹩?wèn)題。

最后發(fā)現(xiàn)在官網(wǎng)上Google也在SDK 6.0的版本將這個(gè)MODE_MULTI_PROCESS標(biāo)識(shí)為deprecated(不贊成使用)。目前來(lái)說(shuō),越來(lái)越多的項(xiàng)目在不斷的膨脹,為了降低單個(gè)進(jìn)程的內(nèi)存占用率,使用"android:process"配置一些組件在單獨(dú)的進(jìn)程中運(yùn)行已經(jīng)是司空見(jiàn)慣了,所以大家在遇到自己的項(xiàng)目有多進(jìn)程時(shí),要注意一下SharedPreferences的問(wèn)題。

小結(jié)

在一個(gè)進(jìn)程中,SharedPreference往往建單個(gè)實(shí)例就可以了,一般不會(huì)出現(xiàn)并發(fā)沖突,如果對(duì)提交的結(jié)果不關(guān)心的話,建議使用apply,當(dāng)然需要確保提交成功且有后續(xù)操作的話,還是需要用commit的。

因?yàn)镾haredPreferences在多進(jìn)程方面的問(wèn)題,大家也可以思考下能不能自己實(shí)現(xiàn)一個(gè)加強(qiáng)版的SharedPreferences解決這些問(wèn)題,網(wǎng)上也有一些開(kāi)源的替代方案,如Github上的tray。(建議大家先想一下,再看這個(gè)項(xiàng)目。)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,023評(píng)論 25 709
  • Android上常見(jiàn)的數(shù)據(jù)存儲(chǔ)方式有哪些呢? SharedPreferences這種存儲(chǔ)數(shù)據(jù)的方式我們平時(shí)用的都對(duì)...
    編程小豬閱讀 4,671評(píng)論 0 5
  • (一)Android面試題(一)Activity、Intent Android四大組件分別是哪些?各自有什么作用和...
    Itachi001閱讀 4,537評(píng)論 4 95
  • 我自己看到自己的時(shí)常感覺(jué)自己沒(méi)有精神,不知道是為什么,不知道是我不想做的事情導(dǎo)致我沒(méi)有精神還是我平常的自說(shuō)自話導(dǎo)致...
    張志鵬_7bba閱讀 253評(píng)論 0 0
  • 一 已是黃昏時(shí)分,女人正獨(dú)自坐在咖啡廳中,穿著最心儀的衣服,配著最精美的飾物,好一個(gè)幸福女人的樣子!可是她的眼神卻...
    Lealie閱讀 373評(píng)論 2 1

友情鏈接更多精彩內(nèi)容