观察者和线程

时间:2012-09-26 12:58:20

标签: java android

在我的Android应用程序中,我有一个Observable Data类,其中包含一个方法download()来下载和解析一些数据。完成后,它会通知其Observer

此外,我有ActivityServiceActivity使用download()异步调用AsyncTask方法。

Service经常需要监听更新以进一步处理数据。这不应该发生在UI线程中。我创建了这个小Service类:

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        new MyWorkerThread().start();
    }

    private class MyWorkerThread extends Thread implements Observer{

        @Override
        public void run() {
            observeData();
        }

        private void observeData(){
            Data.getInstance().addObserver(this);
        }

            @Override
            public void update(Observable observable, Object data) {
               // In what thread does the code placed here run?
            }
    }
}

现在,我的问题是:当download()类的Data方法通知其Observer时,update()方法将在哪个线程运行?这是否在AsyncTask创建的Activity的主题中,这会阻止代码在服务完成之前通过onPostExecute()方法?如果是这样,我最好还是MyService Observer并且每次都创建一个新的MyWorkerThread吗? 或者代码是否会由MyWorkerThread

在自己的线程中运行

我希望这是可以理解的,提前谢谢!

3 个答案:

答案 0 :(得分:2)

答案就在这里

  

当Data类的download()方法通知其Observers

在与update方法相同的线程中将被调用(它将与download方法运行在同一个线程中 - 据我所知,它会通知其观察者。

正如zapl发布的那样,MyWorkerThread在观察数据(observeData();)后完成。

为了在不同的线程中运行,你应该写一些类似的东西:

private class MyWorkerThread extends Thread implements Observer{

    @Override
    public void run() {
        observeData();
    }

    private void observeData(){
        Data.getInstance().addObserver(this);
    }

        @Override
        public void update(Observable observable, Object data) {
            this.start(); //will execute observeData(); in a new thread
        }
}

答案 1 :(得分:1)

  

我想每次调用notifyObservers方法时,我最好创建一个新的线程

你可以这样做,但你不必这样做。例如,使用单个HandlerThread可以实现相同的目标。此外,您不必处理并行运行的多个线程。

public class ObserverService extends Service {

    private Looper mLooper;

    private void onDataChanged() {
        // do whatever you need.
        // This is executed in a background thread.
    }

    @Override
    public void onCreate() {
        HandlerThread ht = new HandlerThread("ObserverService");
        ht.start();
        mLooper = ht.getLooper();
        final Handler handler = new Handler(mLooper) {
            @Override
            public void handleMessage(Message msg) {
                // executed in background HandlerThread
                onDataChanged();
            }
        };
        Observer observer = new Observer() {
            @Override
            public void update(Observable observable, Object data) {
                // this is executed in whatever thread notifies
                // enqueue max 1 messages.
                handler.removeMessages(1234);
                handler.sendEmptyMessage(1234);
            }
        };
        // register observer that send message to background thread.
        Data.getInstance().addObserver(observer);
    }

    @Override
    public void onDestroy() {
        mLooper.quit();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

答案 2 :(得分:0)

    Executor executor = Executors.newCachedThreadPool();
    Observer<MyData> observer = data -> executor.execute(() -> onMyDataChanged(data));
    MyData.getInstance().observeForever(observer);