欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OnSharedPreferenceChangeListener詳解及出現(xiàn)不觸發(fā)解決辦法

 更新時間:2016年08月31日 16:24:43   作者:技術(shù)小黑屋  
本文主要介紹 Android OnSharedPreferenceChangeListener的知識,在Android應(yīng)用開發(fā)過程中會遇到監(jiān)聽器不觸發(fā)事件問題,這里介紹了相應(yīng)的解決辦法

之前使用OnSharedPreferenceChangeListener,遇到了點小問題,就是有些時候OnSharedPreferenceChangeListener沒有被觸發(fā)。最近花了點時間研究了一下,小做整理。本文將會介紹監(jiān)聽器不被觸發(fā)的原因,解決方法,以及其中隱含的一些技術(shù)細節(jié)。

問題再現(xiàn)

OnSharedPreferenceChangeListener是Android中SharedPreference文件發(fā)生變化的監(jiān)聽器。通常我們想要進行監(jiān)聽,會實現(xiàn)如下的代碼。

protected void onCreate(Bundle savedInstanceState) {
 PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
  .registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
  @Override
  public void onSharedPreferenceChanged(
   SharedPreferences sharedPreferences, String key) {
   Log.i(LOGTAG, "testOnSharedPreferenceChangedWrong key =" + key);
  }
 });
}

這種寫法看上去沒有什么問題,而且很多時候開始幾次onSharedPreferenceChanged方法也可以被調(diào)用。但是過一段時間(簡單demo不容易出現(xiàn),但是使用DDMS中的gc會立刻導致接下來的問題),你會發(fā)現(xiàn)前面的方法突然不再被調(diào)用,進而影響到程序的處理。

原因剖析

簡而言之,就是你注冊的監(jiān)聽器被移除掉了。
首先我們先了解一下registerOnSharedPreferenceChangeListener注冊的實現(xiàn)。

private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
   new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
//some code goes here
public void More ...registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
 synchronized(this) {
  mListeners.put(listener, mContent);
 }
}

從上面的代碼可以得知,一個OnSharedPreferenceChangeListener對象實際上是放到了一個WeakHashMap的容器中,執(zhí)行完示例中的onCreate方法,這個監(jiān)聽器對象很快就會成為垃圾回收的目標,由于放在WeakHashMap中作為key不會阻止垃圾回收,所以當監(jiān)聽器對象被回收之后,這個監(jiān)聽器也會從mListeners中移除。所以就造成了onSharedPreferenceChanged不會被調(diào)用。

關(guān)于WeakHashMap相關(guān),請閱讀譯文:理解Java中的弱引用進而更多了解。

如何解決

改為對象成員變量(推薦)

將監(jiān)聽器作為Activity的一個成員變量,在Activity的onResume進行注冊,在onPause時進行注銷。推薦在這兩個Activity生命周期中進行處理,尤其是當SharedPreference值發(fā)生變化后,對Activity展示的UI進行處理操作的情況。這種方法是最推薦的解決方案。

private OnSharedPreferenceChangeListener mListener = new OnSharedPreferenceChangeListener() {

 @Override
 public void onSharedPreferenceChanged(
  SharedPreferences sharedPreferences, String key) {
  Log.i(LOGTAG, "instance variable key=" + key);
 }
};

@Override
protected void onResume() {
 PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(mListener);
 super.onResume();
}

@Override
protected void onPause() {
 PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).unregisterOnSharedPreferenceChangeListener(mListener);
 super.onPause();
}

改為靜態(tài)變量(不推薦)

如下,將一個指向匿名的內(nèi)部類對象的變量sListener使用static修飾,這個內(nèi)部類對象則不會持有外部類的引用。
但是這種做法并不推薦,因為一個靜態(tài)變量和與外部實例不相關(guān),我們很難和外部實例進行一些操作。

private static OnSharedPreferenceChangeListener sListener = new OnSharedPreferenceChangeListener() {
 @Override
 public void onSharedPreferenceChanged(
  SharedPreferences sharedPreferences, String key) {
  Log.i(LOGTAG, "static variable key=" + key);
 }
};

為什么這樣設(shè)計

可能會有人認為這是系統(tǒng)設(shè)計的貓膩或者bug,其實不然,這正是Android設(shè)計人員的高明之處。

正如我們示例的代碼一樣,將一個(隱式的)局部變量添加到監(jiān)聽器容器中,如果該容器只是一個普通的HashMap,這樣會導致內(nèi)存泄露,因為該容器還有局部變量指向的對象,該對象又隱式持有外部Activity的對象,導致Activity無法被銷毀。關(guān)于非靜態(tài)內(nèi)部類持有隱式持有外部類引用,請參考細話Java:”失效”的private修飾符

除此之外,因為局部變量無法在其所在方法外部訪問,這樣就導致了我們只可以使用方法中使用局部變量就行注冊,在合適的時機卻無法使用局部變量進行注銷。

以上就是對 Android OnSharedPreferenceChangeListener的介紹,以及出現(xiàn)問題解決辦法,謝謝大家對本站的支持!

相關(guān)文章

  • Android搜索框通用版

    Android搜索框通用版

    這篇文章主要為大家詳細介紹了Android搜索框通用版的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Android反編譯代碼和防止反編譯

    Android反編譯代碼和防止反編譯

    這篇文章主要介紹了Android反編譯代碼和防止反編譯的相關(guān)資料,需要的朋友可以參考下
    2015-07-07
  • Android Studio和Gradle使用不同位置JDK的問題解決

    Android Studio和Gradle使用不同位置JDK的問題解決

    這篇文章主要介紹了Android Studio和Gradle使用不同位置JDK的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • android暫?;蛲V蛊渌魳凡シ牌鞯牟シ艑崿F(xiàn)代碼

    android暫停或停止其他音樂播放器的播放實現(xiàn)代碼

    來自android自帶的music源碼,下面是廣播接收的代碼,通過發(fā)送廣播來控制音樂的播放,停止等
    2013-11-11
  • Android自定義垂直拖動seekbar進度條

    Android自定義垂直拖動seekbar進度條

    這篇文章主要為大家詳細介紹了Android自定義垂直拖動seekbar進度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • android recyclerview模擬聊天界面

    android recyclerview模擬聊天界面

    這篇文章主要為大家詳細介紹了android Listview模擬聊天界面的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Suspend函數(shù)與回調(diào)的互相轉(zhuǎn)換示例詳解

    Suspend函數(shù)與回調(diào)的互相轉(zhuǎn)換示例詳解

    這篇文章主要為大家介紹了Suspend函數(shù)與回調(diào)的互相轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 使用Kotlin實現(xiàn)文字漸變TextView的代碼

    使用Kotlin實現(xiàn)文字漸變TextView的代碼

    這篇文章主要介紹了使用Kotlin實現(xiàn)文字漸變TextView的代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • Android實現(xiàn)閱讀進度記憶功能

    Android實現(xiàn)閱讀進度記憶功能

    這篇文章主要介紹了Android實現(xiàn)閱讀進度記憶功能,Android控件WebView實現(xiàn)保存閱讀進度,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android APK優(yōu)化工具Zipalign詳解

    Android APK優(yōu)化工具Zipalign詳解

    本文主要介紹Android APK優(yōu)化工具Zipalign,這里整理了相關(guān)資料,并詳細介紹如何使用Zipalign工具及使用技巧,有需要的小伙伴可以參考下
    2016-09-09

最新評論