zoukankan      html  css  js  c++  java
  • OnSharedPreferenceChangeListener不被调用原理及解决方案

    问题再现

    OnSharedPreferenceChangeListener是Android中SharedPreference文件发生变化的监听器。通常我们想要进行监听,会实现如下的代码。

    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方法也可以被调用。但是过一段时间(简单demo 不容易出现,但是使用DDMS中的gc会立刻导致接下来的问题),你会发现前面的方法突然不再被调用,进而影响到程序的处理。

    原因剖析

    简而言之,就是你注册的监听器被移除掉了。首先我们先了解一下registerOnSharedPreferenceChangeListener注册的实现。

    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的容 器中,执行完示例中的onCreate方法,这个监听器对象很快就会成为垃圾回收的目标,由于放在WeakHashMap中作为key不会阻止垃圾回收, 所以当监听器对象被回收之后,这个监听器也会从mListeners中移除。所以就造成了onSharedPreferenceChanged不会被调 用。

    关于WeakHashMap相关,请阅读 译文:理解Java中的弱引用 进而更多了解。

    如何解决

    改为对象成员变量(推荐)

    将监听器作为Activity的一个成员变量,在Activity的onResume进行注册,在onPause时进行注销。推荐在这两个 Activity生命周期中进行处理,尤其是当SharedPreference值发生变化后,对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();
    }
    (后略)
  • 相关阅读:
    关于欧拉函数
    JavaWeb技术
    jQuery介绍
    Spring之事务管理
    Hibernate课堂笔记
    JSON简介
    Ajax简介
    Java代码生成图片验证码
    JAVA学习笔记——ClassLoader中getResource方法的路径参数
    JAVA OOP学习笔记——多态(polymorphism)
  • 原文地址:https://www.cnblogs.com/mgstone/p/5802384.html
Copyright © 2011-2022 走看看