Ale*_*ado 20 java android android-asynctask
回答完这个问题之后,我对使用Android的AsyncTask类的get()方法的意义/用处产生了疑问.
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves its result.
Run Code Online (Sandbox Code Playgroud)
基本上,AsyncTask类的同步解决方案,阻止(冻结)UI直到后台操作完成.
除了测试目的,甚至在那些情况下,我无法真正想到它实际上是一个很好的解决方案,但我可能是错的,所以我感到好奇.
如果您需要用户实际等到AsyncTask完成,您可以显示Dialog或ProgressDialog,在每个时刻都可以控制UI.我知道它不完全相同,但恕我直言,它比使用该get()方法更好的方法.
Sto*_*lly 18
AsyncTask不是进行后台操作的唯一方法.实际上,文档说AsyncTask只应该用于操作最多只需几秒钟.因此,如果您的任务需要更长时间,则应通过实现可运行接口的类对其进行编码.其他(非AsyncTask)线程中的此类任务可能希望等待AsyncTask完成,因此在我看来,没有人想要使用的情况AsyncTask.get()是错误的.
更新:在回复评论时,为了强调这可能是一种有效的用途AsyncTask.get(),以下是可能的:
AsyncTask从UI线程发起的,其可能涉及通过因特网进行通信,例如加载网页或与服务器通信.无论结果是什么AsyncTask,都需要一些(或全部)结果来更新屏幕.因此AsyncTask,它doInBackground跟随onPostExecuteUI线程是有意义的.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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Update2.我发现了另一种可能的有效用途AsyncTask.get().标准建议不是AsyncTask.get()从UI线程使用,因为它会导致用户界面冻结,直到结果可用.但是,对于需要隐身的应用程序,这可能正是所需要的.那么下面的情况如何:詹姆斯·邦德闯入Le Chiffre的酒店房间,只有几分钟的时间从villian手机中提取所有数据并安装监控病毒.他安装Q提供的应用程序并开始运行,但他听到有人来,所以他必须隐藏. Le Chiffre进入房间然后拿起电话拨打电话.几秒钟后,手机似乎有点反应迟钝,但突然手机响起,他不停地想着打电话.当然,没有反应的原因是Q的应用程序正在运行.它有各种各样的任务要做,其中一些需要按特定的顺序完成.该应用程序使用两个线程来完成工作,即UI线程本身和处理AsyncTasks 的单个后台线程.UI线程完全控制所有任务,但由于某些任务需要在其他任务之前完成,因此AsyncTask.get()在等待后台任务完成时使用的UI线程中存在点:-).
get永远不要在UI线程中使用该方法,因为它会(如您所见)冻结您的UI.它应该在后台线程中用于等待任务的结束,但一般来说,尽量避免AsyncTask(为什么?).
我建议使用回调或eventbus作为替代品.