线程块ContentObserver

时间:2013-05-12 00:08:02

标签: android multithreading contentobserver

我正在处理的应用程序必须对日历或事件数据库中的更改做出反应,因此下面的Observer将使用URI进行注册:

  

content://com.android.calendar(适用于旧版设备:内容://日历)

“问题”是当各个数据发生变化时,观察者会(有时)多次调用。如果我注册两个单独的ContentResolver,一个用于... /日历,一个用于... /事件,它们仍然经常被多次调用。我尝试使用以下代码实现的是缓冲那些多次调用,因为ContentResolver本身调用了一个运行大量代码的服务。因此,服务应该只在短时间内为许多ContentObserver调用调用一次。

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());
    }
}

我解决这个问题的想法是,如果保存的值(来自SharedPreferences的“int first”)等于1,则生成一个线程。如果观察者在该线程休眠时被另一次调用,则该值将被提升并且线程会再次入睡......

不幸的是,线程会阻止其他传入的调用,因此它的循环永远不会被扩展。我的原始代码中的Logs告诉我,在完成Thread之后,SharedPreferences会被更改!

  • 有人为我提供解决方案吗? (我是线程新手......)
  • 我应该为此缓冲工作实施其他服务吗?
  • 概述:将Context转移到ContentObserver是否可以?

提前致谢! ;)

1 个答案:

答案 0 :(得分:1)

我发现了我犯的错误:

而不是调用 buffer.run(),我不得不通过 buffer.start()实际启动线程,因为调用.run()只执行实现运行方法......

  

换句话说,实例化线程的客户端代码不应该在新实例化的线程上调用run()方法。因为在线程对象上调用run()方法会立即执行run()方法中的步骤违背了多线程编程的目的,就同时运行的线程的执行顺序而言,这基本上是一种非确定性的。

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