回答后this问题,我对使用 Android 的 AsyncTask 类的 get() 方法的意义/有用性有疑问。
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves its result.
基本上,是 AsyncTask 类的同步解决方案,它会阻塞(卡住)UI,直到后台操作完成。
除了测试目的之外,即使在那些情况下,我也无法真正想到它实际上是一个好的解决方案,但我可能错了,所以我感到好奇。
如果您需要用户真正等到 AsyncTask 完成,您可以显示一个 Dialog 或 ProgressDialog,随时控制 UI。我知道这并不完全相同,但恕我直言,这是一种比使用 get()
方法更好的方法。
最佳答案
AsyncTask
并不是进行后台操作的唯一方式。事实上,文档说 AsyncTask
应该只用于最多需要几秒钟的操作。因此,如果您的任务需要更长的时间,则应通过实现 the runnable interface 的类对其进行编码。 .其他(非 AsyncTask)线程中的此类任务很可能希望等待 AsyncTask
完成,因此在我看来,没有人想要使用 AsyncTask 的情况的想法.get()
为假。
更新:为了回应评论,强调这可能是对 AsyncTask.get()
的有效使用,以下是可能的:
- 可能有从 UI 线程启动的
AsyncTask
,这可能涉及通过 Internet 进行通信,例如加载网页,或与服务器通信。无论AsyncTask
的结果是什么,都需要部分(或全部)结果来更新屏幕。因此,UI 线程上的AsyncTask
及其doInBackground
后跟onPostExecute
是有意义的。 - 每当 UI 线程启动一个
AsyncTask
,它将AsyncTask
对象放入队列中,以便在结果可用后由单独的后台线程进行额外处理。 - 对于每个
AsyncTask
依次在队列中,后台线程使用AsyncTask.get()
等待任务完成,然后再进行附加处理。一个明显的附加处理示例可以简单地将所有此类AsyncTask
Activity 记录到 Internet 上的服务器,因此在后台执行此操作是有意义的。
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。 AsyncTask.get()
的另一种可能的有效用途发生在我身上。标准建议是不要在 UI 线程中使用 AsyncTask.get()
,因为它会导致用户界面卡住,直到结果可用。但是,对于需要隐身的应用程序,这可能正是所需要的。那么下面的情况呢:James Bond闯入Le Chiffre的酒店房间并且只有几分钟的时间从小人的手机中提取所有数据并安装监控病毒。他安装了Q 提供的应用程序并开始运行,但他听到有人来了,所以他不得不躲起来。 Le Chiffre进了房间,拿起手机打电话。几秒钟后,手机似乎有点没 react ,但突然手机醒来,他没有多想就拨通了电话。当然,没有响应的原因是 Q的应用程序正在运行。它有各种各样的任务要做,其中一些需要按照特定的顺序完成。该应用程序使用两个线程来完成工作,即 UI 线程本身和处理 AsyncTask
的单个后台线程。 UI 线程全面控制所有任务,但由于某些任务需要在其他任务之前完成,因此在应用程序中存在一些点,即 UI 线程在等待时使用 AsyncTask.get()
要完成的后台任务:-)。
关于java - AsyncTask 的 get() 方法 : Is there any scenario where it is actually the best option?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16912768/