AsyncTask
不是进行后台操作的唯一方法。事实上,文档说这AsyncTask
应该只用于操作最多需要几秒钟。因此,如果您的任务需要更长的时间,则应通过实现可运行接口的类对其进行编码。其他(非 AsyncTask)线程中的此类任务很可能希望等待 anAsyncTask
完成,因此在我看来,没有人想要使用的情况的想法AsyncTask.get()
是错误的。
更新:作为对评论的回应,为了强调这可能是对 的有效使用AsyncTask.get()
,以下是可能的:
- 可能有
AsyncTask
从 UI 线程启动的 s,这可能涉及通过 Internet 进行通信,例如加载网页或与服务器通信。无论结果如何,AsyncTask
都需要部分(或全部)结果来更新屏幕。因此,在 UI 线程上AsyncTask
使用doInBackground
其后跟onPostExecute
是有意义的。 - 每当 UI 线程启动
AsyncTask
时,它会将AsyncTask
对象放入队列中,以便在结果可用后由单独的后台线程进行额外处理。 - 对于
AsyncTask
队列中的每一个,后台线程用于AsyncTask.get()
等待任务完成,然后再进行额外的处理。附加处理的一个明显示例可能只是将所有此类AsyncTask
活动记录到 Internet 上的服务器,因此在后台执行此操作是有意义的。
下面的代码说明了我的意思。
KickOffAsynctask(...)
该应用程序在它想要执行 AsyncTask 时调用,并且有一个后台线程会在任务完成后自动拾取任务进行后处理。
public class MyActivity extends Activity {
static class MyAsyncTaskParameters { }
static class MyAsyncTaskResults { }
Queue<MyAsyncTask> queue; // task queue for post-processing of AsyncTasks in the background
BackgroundThread b_thread; // class related to the background thread that does the post-processing of AsyncTasks
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
queue = new ConcurrentLinkedQueue<MyAsyncTask>();
b_thread = new BackgroundThread(queue);
b_thread.Start();
}
void KickOffAsynctask(MyAsyncTaskParameters params) {
MyAsyncTask newtask = new MyAsyncTask();
newtask.execute(params);
synchronized(queue) {
queue.add(newtask);
}
}
static class MyAsyncTask extends AsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> {
@Override
protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) {
MyAsyncTaskResults results = new MyAsyncTaskResults();
// do AsyncTask in background
return results;
}
@Override
protected void onPostExecute(MyAsyncTaskResults res){
// take required results from MyAsyncResults for use in the user interface
}
}
static class BackgroundThread implements Runnable {
// class that controls the post processing of AsyncTask results in background
private Queue<MyAsyncTask> queue;
private Thread thisthread;
public boolean continue_running;
public BackgroundThread(Queue<MyAsyncTask> queue) {
this.queue=queue; thisthread = null; continue_running = true;
}
public void Start() {
thisthread = new Thread(this);
thisthread.start();
}
@Override
public void run() {
try {
do {
MyAsyncTask task;
synchronized(queue) {
task = queue.poll();
}
if (task == null) {
Thread.sleep(100);
} else {
MyAsyncTaskResults results = task.get();
// post processing of AsyncTask results in background, e.g. log to a server somewhere
}
} while (continue_running);
} catch(Throwable e) {
e.printStackTrace();
}
}
}
}
更新2。我想到了另一个可能的有效用法AsyncTask.get()
。标准建议不要AsyncTask.get()
从 UI 线程使用,因为它会导致用户界面冻结,直到结果可用。但是,对于需要隐身的应用程序,这可能正是所需要的。那么下面的情况如何:詹姆斯邦德闯入Le Chiffre的酒店房间,只有几分钟的时间从恶棍的手机中提取所有数据并安装监控病毒。他安装了Q提供的应用程序并开始运行,但他听到有人来了,所以他不得不躲起来。 雪佛兰进了房间,拿起手机打电话。几秒钟后,手机似乎有点没反应,但突然手机醒来,他没有多想就拨通了电话。当然,无响应的原因是Q的应用程序正在运行。它有各种各样的任务要做,其中一些需要按照特定的顺序完成。该应用程序使用两个线程来完成这项工作,即 UI 线程本身和处理AsyncTask
s 的单个后台线程。UI 线程完全控制所有任务,但由于某些任务需要在其他任务之前完成,因此在应用程序中存在一些点,UI 线程AsyncTask.get()
在等待后台任务完成时使用 :-)。