AsyncTask
不是执行后台操作的唯一方法。事实上,文档说,这应该只用于最多需要几秒钟的操作。因此,如果你有需要更长的时间的任务,应该通过实现可运行接口的类来编码它们。其他(非 AsyncTask)线程中的此类任务可能很想等待 完成,因此在我看来,没有想要使用的情况的想法是错误的。AsyncTask
AsyncTask
AsyncTask.get()
更新:作为对注释的回应,为了强调这可能是 的有效用法,以下是可能的:AsyncTask.get()
- 可能有一些是从UI线程启动的,这可能涉及通过Internet进行通信,例如加载网页或与服务器通信。无论结果如何,都需要一些(或全部)结果来更新屏幕。因此,在 UI 线程上后跟 a 是有意义的。
AsyncTask
AsyncTask
AsyncTask
doInBackground
onPostExecute
- 每当 UI 线程启动 时,它都会将对象放在队列中,以便在结果可用后由单独的后台线程进行其他处理。
AsyncTask
AsyncTask
- 对于队列中的每个线程,后台线程在执行其他处理之前,将使用等待任务完成。额外处理的一个明显示例可能只是将所有此类活动记录到Internet上的服务器,因此在后台执行此操作是有意义的。
AsyncTask
AsyncTask.get()
AsyncTask
下面的代码显示了我的意思。每当应用想要执行 AsyncTask 时,它就会调用,并且有一个后台线程,该线程将在任务完成后自动选取任务进行后处理。
KickOffAsynctask(...)
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.另一个可能的有效用法已经发生在我身上。标准建议不要从 UI 线程使用,因为这会导致用户界面冻结,直到结果可用。但是,对于需要隐身的应用程序,这可能正是所需的。那么接下来的情况如何:詹姆斯·邦德闯入Le Chiffre的酒店房间,只有几分钟的时间从维利安的手机中提取所有数据并安装监控病毒。他安装了Q提供的应用程序并开始运行,但他听到有人来了,所以他不得不躲起来。Le Chiffre进入房间,拿起手机打电话。几秒钟后,电话似乎有点反应迟钝,但突然电话响起,他不假思索地打了电话。当然,无响应的原因是Q的应用程序正在运行。它有各种任务要做,其中一些需要按特定顺序完成。该应用使用两个线程来完成工作,即 UI 线程本身和处理 s 的单个后台线程。UI线程可以全面控制所有任务,但由于某些任务需要先于其他任务完成,因此在等待后台任务完成时,应用中存在UI线程使用的点:-)。AsyncTask.get()
AsyncTask.get()
AsyncTask
AsyncTask.get()