Before using Onsharedpreferencechangelistener, there is a small problem, that is, sometimes onsharedpreferencechangelistener is not triggered. Recently spent a little time studying, small do tidy up. This article will explain why the listener is not triggered, how to fix it, and some of the technical details implied therein.
Problem reappearance
Onsharedpreferencechangelistener is a listener for changes in sharedpreference files in Android. Usually we want to listen, and we will implement the following code.
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);
}
);
}
This style of writing does not seem to be a problem, and many times the Onsharedpreferencechanged method can be invoked. But over time (simple demo is not easy to come by, but using GC in DDMS will immediately cause the next problem), you will find that the previous method is suddenly no longer invoked, which in turn affects the processing of the program.
Cause analysis
In short, your registered listener has been removed.
First, let's take a look at the implementation of Registeronsharedpreferencechangelistener registration.
Private final Weakhashmap<onsharedpreferencechangelistener, object> mlisteners =
new weakhashmap< Onsharedpreferencechangelistener, object> ();
Some code goes here is public void more ...
registeronsharedpreferencechangelistener ( Onsharedpreferencechangelistener listener) {
synchronized (this) {
mlisteners.put (Listener, mcontent);
}
}
As you can see from the code above, a Onsharedpreferencechangelistener object is actually placed in a Weakhashmap container, and after the OnCreate method in the example, the Listener object will soon be the target of garbage collection. , because a key in Weakhashmap does not prevent garbage collection, the listener is removed from the mlisteners after the listener object is reclaimed. So it caused the onsharedpreferencechanged not to be invoked.
For weakhashmap related, read: Understand weak references in Java and learn more about them.
How to Solve
Change to object member variable (recommended)
The listener is used as a member variable of the activity, registered at the onresume of the activity, and logged out at OnPause. This is recommended for processing in these two activity lifecycles, especially when the sharedpreference values are changed to handle the UI being displayed by the event. This approach is the most recommended solution.
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 ();
}
Change to static variable (not recommended)
as follows, a variable slistener that points to an anonymous internal class object is used with the static modifier, which does not hold a reference to the external class.
This practice is not recommended, however, because a static variable is not relevant to an external instance, and it is difficult to do something with an external instance.
private static Onsharedpreferencechangelistener Slistener = new Onsharedpreferencechangelistener () {
@Override Public
void onsharedpreferencechanged (
sharedpreferences sharedpreferences, String key) {
log.i (LogTag, "Static variable key=" + key);
}
;
Why do you design this way
Some might think that this is a trick or a bug in the system design, which is the genius of Android designers.
As our example code, adding an (implicit) local variable to the listener container, if the container is just a normal hashmap, can cause a memory leak because the container also has an object that the local variable points to, and that object implicitly holds the object of the external activity. Causes the activity to not be destroyed. For a non-static inner class holding an implicit hold of an external class reference, refer to the private modifier of the Java: invalid
In addition, because local variables cannot be accessed outside of the method in which they are located, we can only use local variables in the method to register the row, but we cannot use local variables to log off at the right time.
The above is the introduction of the Android Onsharedpreferencechangelistener, as well as the problem solution, thank you for your support to this site!