【问题标题】:Listener behavior in relation to Activity lifecycle与 Activity 生命周期相关的侦听器行为
【发布时间】:2014-01-18 13:18:27
【问题描述】:

我有一个带有私有 OnSharedPreferenceChangeListener 的 Activity,监听器的工作是在 Activity 的 onCreate() 方法上定义的。侦听器注册到应用程序的 sharedPreferences。

更改本身由服务触发,以响应收到的短信意图。

当Activity本身死亡时,监听器会收到回调吗?有没有不会的情况?

监听器被定义(大致):

private OnSharedPreferenceChangeListener _sharedPreferenceListener;

public void onCreate(Bundle bundle){
...
_prefs = PreferenceManager.getDefaultSharedPreferences(this);
_prefs.registerOnSharedPreferenceChangeListener(_sharedPreferenceListener);
...
_sharedPreferenceListener = new SharedPreferences.OnSharedPreferenceChangeListener(){ /*doing some work here*/};
...
}

如果正确与否,请忽略此处的逻辑,假设代码有效,我主要关心的是侦听器如何对活动生命周期中的变化做出反应。

谢谢,

【问题讨论】:

    标签: android callback listener sharedpreferences android-lifecycle


    【解决方案1】:

    实际上,由于监听器对活动一无所知(因此您可以在任何地方使用它,而不仅仅是在活动中),无论您在哪里使用它都会收到通知。

    另外,因为你不能确定它对 context 做了什么,所以在这种情况下你应该使用应用程序上下文(这样你就不会发生内存泄漏,尽管我怀疑它需要引用活动)。

    当然,如果监听器本身被弱引用引用,并且活动在任何其他类上没有对自身的任何引用,那么监听器也可以被 GC-ed。您可以在 Android 的代码(或至少 API 19)中看到,在“android.app.SharedPreferencesImpl”类(示例链接here)中,您有一个 WeakHashMap 的侦听器,所以这可能意味着托管侦听器的活动可以被 GC-ed,因此侦听器将停止被调用。以下是Android的相关代码:

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

    所以,正如我所写的,最好只是放置应用程序上下文,以防您希望继续收听此事件。

    或者,如果您确实希望停止侦听此事件,只需在 Activity 被销毁时取消注册即可。

    为了证明这一点,您可以简单地运行您的应用程序...

    这是我的证明应用程序:

    MainActivity.java

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            preferences.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
    
                @Override
                public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
                    android.util.Log.d("AppLog", "changed!");
                }
            });
            new Handler().postDelayed(new Runnable() {
    
                @Override
                public void run() {
                    startActivity(new Intent(MainActivity.this, Activity2.class));
                }
            }, 1000);
            finish();
        }
    
    }
    

    Activity2.java

    public class Activity2 extends Activity {
    
        @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_activity2);
            //if you call here System.gc(); , you have a good chance that the listener won't be called
            new Handler().postDelayed(new Runnable() {
    
                @Override
                public void run() {
                    //this may or may not cause the listener to write to the log
                    final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(Activity2.this);
                    preferences.edit().putBoolean("test", true).commit();
                }
    
            }, 1000);
    
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      Activity本身死亡后,监听器会收到回调吗?

      -> 不,不会的。因为当您的活动终止时,_prefs_sharedPreferenceListener 字段将被销毁。

      您可以在OnSharedPreferenceChangeListener 上查看此问题以获取更多详细信息:

      SharedPreferences.onSharedPreferenceChangeListener not being called consistently

      【讨论】:

      • 只要有来自其他地方的字段/变量的引用,Acitivity 对象就不是真的“死”,所以仍然可以调用监听器。
      【解决方案3】:

      您必须在活动的onDestroy() 中取消注册监听器,否则活动对象将保留在内存中。

      【讨论】:

      • 在大多数情况下这是一件好事,但在这种情况下,它被弱引用引用(至少在特定的 Android 代码上)......但同样,你是对的开发人员应该记得做这样的事情。
      猜你喜欢
      • 2013-04-06
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多