Issue
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,
Solution
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);
}
}
Answered By - android developer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.