实际上,由于监听器对活动一无所知(因此您可以在任何地方使用它,而不仅仅是在活动中),无论您在哪里使用它都会收到通知。
另外,因为你不能确定它对 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);
}
}