Preference On Change Listener

jjNford picture jjNford · Nov 1, 2011 · Viewed 10.3k times · Source

I have read this helpful post :

SharedPreferences.onSharedPreferenceChangeListener not being called consistently

However I am having no luck. I am trying to create an OnSharedPreferenceChangeListener that runs in a service. Everything is implemented correctly but the listener is not always triggered.

public MyServiceOne extends Service {

    public SharedPreferences mSharedPreferences;

    // Listener defined by anonymous inner class.
    public OnSharedPreferenceChangeListener mListener = new OnSharedPreferenceChangeListener() {        

        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            Log.d("debug", "A preference has been changed");            
        }
    };

    @Override
    public void onCreate() {            
        mSharedPreferences = getSharedPreferences(MySharedPreferences.NAME, Context.MODE_PRIVATE);
        mSharedPreferences.registerOnSharedPreferenceChangeListener(mListener);
    }

    @Override   
    public void onDestroy() {
        super.onDestroy();
        mSharedPreferences.unregisterOnSharedPreferenceChangeListener(mListener);
    }
}

UPDATE

The problem stems from a fact I did not mention. I am running two services and when shared preference changes are made in MyService2 nothing is triggered. In the manifest I define the services to run in different processes. Is there a way to make this work?

Answer

jjNford picture jjNford · Mar 1, 2012

After gaining some experience with Android I have come back to answer this question and help anyone else who is having trouble with this type of situation.

The implementation of the OnSharedPreferenceChangeListener is correct. The problem lies in the manifest and application architecture. Because the services are running in different processes Android has created difference Dalvik Virtual Machines for each service therefore they do not "hear" each others listeners.

This was just bad design - The better way to approach the idea of running two concurrent services is to create one service that threads each "service" off to run concurrently. This way they can share the same Heap thus sharing the same Objects & Listeners

If someone were determined to use two services they could create a BroadcastReceiver to catch intents for that preferences need to be changed - or communicate through sockets. There are also ways to do this with a ContentProvider (Please NEVER DO THIS). But again, there is no reason for any of this if the design is good.