Question

the app I'm currently working on has to react on changes in the calendar or event database, therefore the Observer below gets registered with the URI:

content://com.android.calendar (for older Devices: content://calendar)

The "problem" is that the Observer gets (sometimes) called several times, when respective data gets changed. If I register two separate ContentResolver, one for .../calendars and one for .../events they still get often called multiple times. What I try to achieve with the following code is to buffer those multiple calls, as the ContentResolver itself calls a service, that would run a lot of code. So the service should only get called once for many ContentObserver calls in a short period of time.

public class Observer extends ContentObserver{

private Context con;

public Observer(Handler handler, Context con) {
    super(handler);
    this.con = con;
}

@Override
public void onChange(boolean selfChange) {
    Log.i("TS", "Änderung an den Kalendern");

    //Gets released after the first Change, waits and checks SharedPrefs in order to buffer multiple Calls in a short period of time!
    //Changes get handled in the Service
    Thread buffer = new Thread(){

        @Override
        public void run() {
            int check = 1, last = 0;

            do{
                try {
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                last = check;
                check = getCurrent();
            } while(last != check);

            releaseIntent();
        }

    };

    SharedPreferences prefs = con.getSharedPreferences(con.getPackageName(), Context.MODE_PRIVATE);
    Editor edit = prefs.edit();

    int first = prefs.getInt(Constants.FIRST_ON_CHANGE, 1);

    if(first == 1)
        buffer.run();

    first++;

    edit.putInt(Constants.FIRST_ON_CHANGE, first);
    edit.commit();

}

//returns the current control-integer from SharedPrefs (for Thread)
private int getCurrent(){
    SharedPreferences prefs = con.getSharedPreferences(con.getPackageName(), Context.MODE_PRIVATE);
    return prefs.getInt(Constants.FIRST_ON_CHANGE, 1);      
}

//releases ContentChanged-Intent for Service, resets SharedPrefs
private void releaseIntent(){
    con.getSharedPreferences(con.getPackageName(), Context.MODE_PRIVATE).edit().putInt(Constants.FIRST_ON_CHANGE, 1).commit();


    AlarmManager alm = (AlarmManager) con.getSystemService(Context.ALARM_SERVICE);
    alm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), new PendingIntentCreator(con).createContentChangedIntent());
    }
}

My idea to solve that problem, was to generate a thread if a saved value ("int first" from SharedPreferences) equals 1. If the observer would get called another time while that thread sleeps, the value would get raised and the thread would sleep again...

Unfortunately the Thread blocks other incoming calls, so that its loop never gets extended. The Logs in my original code, showed me that the SharedPreferences get changed after the Thread is done!

  • Does anybody have a solution for me? (I'm new to threading...)
  • Should I implement another service for this buffering work?
  • General: Is it ok to transfer Context into a ContentObserver?

Thanks in advance! ;)

Was it helpful?

Solution

I found the mistake I've made:

Instead of calling buffer.run(), I had to actually start the thread by buffer.start(), because calling .run() just executes the implementation of the run-method...

In other words, the client code instantiating a thread shouldn't place a call to the run() method on the newly instantiated thread.Because the very fact that calling the run() method on a thread object would immediately execute the steps in the run() method defeats the very purpose of multithreaded programming which is essentially of a non-deterministic nature in terms of order of execution of the concurrently running threads.

http://www.coderanch.com/t/234040/threads/java/Difference-run-start-method-Thread

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top