SharedPreferences.onSharedPreferenceChangeListener not being called consistently

前端 未结 8 1101
终归单人心
终归单人心 2020-11-22 06:47

I\'m registering a preference change listener like this (in the onCreate() of my main activity):

SharedPreferences prefs = PreferenceManager.get         


        
相关标签:
8条回答
  • 2020-11-22 07:21

    Kotlin Code for register SharedPreferenceChangeListener it detect when change will happening on the saved key :

      PreferenceManager.getDefaultSharedPreferences(this)
            .registerOnSharedPreferenceChangeListener { sharedPreferences, key ->
                if(key=="language") {
                    //Do Something 
                }
            }
    

    you can put this code in onStart() , or somewhere else.. *Consider that you must use

     if(key=="YourKey")
    

    or your codes inside "//Do Something " block will be run wrongly for every change that will happening in any other key in sharedPreferences

    0 讨论(0)
  • 2020-11-22 07:28

    So, I don't know if this would really help anyone though, it solved my issue. Even though I had implemented the OnSharedPreferenceChangeListener as stated by the accepted answer. Still, I had an inconsistency with the listener being called.

    I came here to understand that the Android just sends it for garbage collection after some time. So, I looked over at my code. To my shame, I had not declared the listener GLOBALLY but instead inside the onCreateView. And that was because I listened to the Android Studio telling me to convert the listener to a local variable.

    0 讨论(0)
  • 2020-11-22 07:29

    This is a sneaky one. SharedPreferences keeps listeners in a WeakHashMap. This means that you cannot use an anonymous inner class as a listener, as it will become the target of garbage collection as soon as you leave the current scope. It will work at first, but eventually, will get garbage collected, removed from the WeakHashMap and stop working.

    Keep a reference to the listener in a field of your class and you will be OK, provided your class instance is not destroyed.

    i.e. instead of:

    prefs.registerOnSharedPreferenceChangeListener(
      new SharedPreferences.OnSharedPreferenceChangeListener() {
      public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        // Implementation
      }
    });
    

    do this:

    // Use instance field for listener
    // It will not be gc'd as long as this instance is kept referenced
    listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
      public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        // Implementation
      }
    };
    
    prefs.registerOnSharedPreferenceChangeListener(listener);
    

    The reason unregistering in the onDestroy method fixes the problem is because to do that you had to save the listener in a field, therefore preventing the issue. It's the saving the listener in a field that fixes the problem, not the unregistering in onDestroy.

    UPDATE: The Android docs have been updated with warnings about this behavior. So, oddball behavior remains. But now it's documented.

    0 讨论(0)
  • 2020-11-22 07:32

    The accepted answer creates a SharedPreferenceChangeListener every time onResume is called. @Samuel solves it by making SharedPreferenceListener a member of the Activity class. But there's a third and a more straightforward solution that Google also uses in this codelab. Make your activity class implement the OnSharedPreferenceChangeListener interface and override onSharedPreferenceChanged in the Activity, effectively making the Activity itself a SharedPreferenceListener.

    public class MainActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener {
    
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
    
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            PreferenceManager.getDefaultSharedPreferences(this)
                    .registerOnSharedPreferenceChangeListener(this);
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            PreferenceManager.getDefaultSharedPreferences(this)
                    .unregisterOnSharedPreferenceChangeListener(this);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:35

    While reading Word readable data shared by first app,we should

    Replace

    getSharedPreferences("PREF_NAME", Context.MODE_PRIVATE);
    

    with

    getSharedPreferences("PREF_NAME", Context.MODE_MULTI_PROCESS);
    

    in second app to get updated value in second app.

    But still it is not working...

    0 讨论(0)
  • 2020-11-22 07:36

    As this is the most detailed page for the topic I want to add my 50ct.

    I had the problem that OnSharedPreferenceChangeListener wasn't called. My SharedPreferences are retrieved at the start of the main Activity by:

    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    

    My PreferenceActivity code is short and does nothing except showing the preferences:

    public class Preferences extends PreferenceActivity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // load the XML preferences file
            addPreferencesFromResource(R.xml.preferences);
        }
    }
    

    Every time the menu button is pressed I create the PreferenceActivity from the main Activity:

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        //start Preference activity to show preferences on screen
        startActivity(new Intent(this, Preferences.class));
        //hook into sharedPreferences. THIS NEEDS TO BE DONE AFTER CREATING THE ACTIVITY!!!
        prefs.registerOnSharedPreferenceChangeListener(this);
        return false;
    }
    

    Note that registering the OnSharedPreferenceChangeListener needs to be done AFTER creating the PreferenceActivity in this case, else the Handler in the main Activity won't be called!!! It took me some sweet time to realize that...

    0 讨论(0)
提交回复
热议问题