Android:创建一个定期运行并执行UI任务的后台线程?

时间:2015-10-09 15:04:27

标签: android multithreading android-handler

好的,所以我知道如何做一个背景任务,我知道如何做一个周期性的任务(使用句柄postdelayed和runnable),我也知道如何从后台线程(通过处理程序)做UI任务,但我不是能够执行在UI线程上执行某些操作的定期后台任务。

我正在尝试每分钟执行一些后台任务,我必须在其中进行网络呼叫。调用结束后,根据输出我必须更新UI。我试着做这样的事情

private void DoTask() {
        Thread thread = new Thread() {
            public void run() {
                Looper.prepare();
                final Handler handler = new Handler();
                handler.post(netRunnable);
                Looper.loop();
            }
        };
        thread.start();
}

Runnable netRunnable = new Runnable() {
    @Override
    public void run() {
        handler.getLooper().prepare();
        final Handler handler1 = new Handler(Looper.getMainLooper());
        if ( do background work and check result){
            handler1.post(new Runnable() {
                @Override
                public void run() {
                    //Do UI Task
                }
            });
        }
        handler.getLooper().loop();
        handler.postDelayed(netRunnable, 60000);
    }
}

我知道我的实施可能存在一些根本性缺陷,但我不知道如何正确完成这项任务。现在它正在给出Only one Looper may be created per thread的错误。我得到它想说的话。但是,任何人都可以建议以正确的方式做到这一点。

3 个答案:

答案 0 :(得分:2)

您可以使用异步任务。这些是专为它设计的:

http://developer.android.com/reference/android/os/AsyncTask.html

它允许您在后台执行网络调用,然后在获得结果时,在UI线程上执行操作

宣言:

 private class MyTask extends AsyncTask<Input, Void, Output> {
 protected Output doInBackground(Input... inputs) {
       // do something on the network
       return myOutput;// use this to transmit your result
 }

 protected void onPostExecute(Output result) {
     // do something on UI thread with the result
 }

}

如果你想重复它,只需创建一个runnable来启动它,并在每次通话后安排下一个:

MyTask myTask;
Handler handler = new Handler();

    Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                MyTask myTask = new MyTask();
                myTask.execute(myArg);
                handler.postDelayed(netRunnable, 60000); // schedule next call
            }
        }

首次推出:

handler.postDelayed(myRunnable, 60000);

或者,如果您想立即启动它:

handler.post(myRunnable);

当您的活动被销毁时,不要忘记取消任务:

myTask.cancel(true);

答案 1 :(得分:1)

也许你会更好,创建一个单独的(Intent)Service并定期使用postDelayed调用它。在Activity中创建一个BroadcastReceiver并在那里处理UI更改。

处理来自其他线程的UI更改的另一个提示:这是不可能的。因此,您需要调用runOnUiThread。 Here is how to use it

答案 2 :(得分:0)

如果活动经常转换,为什么不转换责任。您可以创建一个执行定期网络任务的服务。

然后,   - 您的活动要么定期调用此服务以获取值。   - 或者你使用一个监听系统:你创建一个你的活动必须实现的接口,以便从任务完成中得到通知