I have an Activity with a private OnSharedPreferenceChangeListener, the listener's work is defined on the onCreate() method of the Activity. The listener is registered to the sharedPreferences of the application.

The change itself is triggered by a Service in response to an sms received intent.

Will the listener receive the callback when the Activity itself has died? are there cases where it will not?

The listener is defined (roughly):

private OnSharedPreferenceChangeListener _sharedPreferenceListener;

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

please igonre the logic here if correct or not, assume that the code works, my main concern is how the listener reacts to changes in the lifecycle of the activity.

Thanks,

有帮助吗?

解决方案

actually, since the listener doesn't know anything about the activity (and as such you can use it anywhere , not just in an activity), you will get notified no matter where you use it.

Also, since you can't know for sure what it does with the context , you should use the application context instead in this case (so that you won't have memory leaks, though I doubt it needs a reference to the activity).

Of course, if the listener itself is referenced by weak reference, and the activity doesn't have any reference to itself on any other class, the listener can be GC-ed too. You can see in the code of Android (or at least of API 19) that in the class "android.app.SharedPreferencesImpl" (example link here) , you have a WeakHashMap of listeners, so it might mean that the activity that hosts the listener can be GC-ed and so the listener will stop from being called. Here is the relavant code of Android:

private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
        new WeakHashMap<OnSharedPreferenceChangeListener, Object>();

...
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
    synchronized(this) {
        mListeners.put(listener, mContent);
    }
}

So, as I've written, best if you just put the application context in case you wish to keep listening to this event.

Or, in case you do wish to stop listening to this event, just unregister it when the activity is being destroyed.

to prove it, you can simply run your app...

here's my proof app:

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

    }

}

其他提示

Will the listener receive the callback when the Activity itself has died?

-> No, it won't. Because when your activity dies, the _prefs and _sharedPreferenceListener fields will be destroyed.

You could check this question for more details on OnSharedPreferenceChangeListener :

SharedPreferences.onSharedPreferenceChangeListener not being called consistently

You must un-register the listener in onDestroy() of activity, else Activity object will stay in memory.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top