AsyncTask 的 get() 方法:是否有任何场景它实际上是最佳选择? [英] AsyncTask's get() method: Is there any scenario where it is actually the best option?

查看:25
本文介绍了AsyncTask 的 get() 方法:是否有任何场景它实际上是最佳选择?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答这个之后 问题,我对使用 Android 的 AsyncTask 类的 get() 方法的意义/有用性有疑问.

After answering this question, I got a doubt about the sense/usefulness of using the get() method of Android's AsyncTask class.

public final Result get ()

Waits if necessary for the computation to complete, and then retrieves its result. 

基本上是 AsyncTask 类的同步解决方案,它阻塞(冻结)UI,直到后台操作完成.

Basically, a synchronous solution to the AsyncTask class, that blocks (freezes) the UI until the background operations are finished.

除了测试目的,即使在那些情况下,我也无法真正想到它实际上是一个好的解决方案的任何场景,但我可能是错的,所以我感到很好奇.

Other than test purposes, and even in those cases, I can't really think in any scenario where it is actually a good solution, but I may be wrong, so I feel curious.

如果您需要用户真正等到 AsyncTask 完成,您可以显示一个 Dialog 或 ProgressDialog,以随时控制 UI.我知道这并不完全相同,但恕我直言,它比使用 get() 方法要好得多.

If you need the user to actually wait until the AsyncTask finishes, you can show a Dialog or ProgressDialog, having the control of the UI in every moment. I know it's not exactly the same, but IMHO it's a much better approach than using the get() method.

推荐答案

AsyncTask 不是进行后台操作的唯一方法.事实上,文档说 AsyncTask 应该只用于最多需要几秒钟的操作.因此,如果您的任务需要更长时间,则应通过实现 可运行的界面.其他(非 AsyncTask)线程中的此类任务很可能希望等待 AsyncTask 完成,因此在我看来,没有人想要使用 AsyncTask.get() 是假的.

AsyncTask isn't the only way of doing background operations. Indeed, the documentation says that AsyncTask should only be used for operations take at most a few seconds. So if you've got tasks that take longer, they should be coded via classes that implement the runnable interface. Such tasks in other (non AsyncTask) threads may well want to wait for an AsyncTask to finish, so it seems to me that the idea that there are no situations where one would want to use AsyncTask.get() is false.

更新:为了回应评论,强调这可能是 AsyncTask.get() 的有效使用,以下是可能的:

  • 可能有从 UI 线程启动的 AsyncTask ,这可能涉及通过互联网进行通信,例如加载网页,或与服务器通信.无论 AsyncTask 的结果是什么,更新屏幕都需要部分(或全部)结果.因此,UI 线程上带有 doInBackgroundonPostExecuteAsyncTask 是有意义的.
  • 每当 UI 线程启动一个AsyncTask,它将AsyncTask 对象放入队列中,以便在结果可用时由单独的后台线程进行额外处理.
  • 对于每个AsyncTask 依次在队列中,后台线程使用 AsyncTask.get() 等待任务完成,然后再做额外的处理.附加处理的一个明显示例可能只是将所有此类 AsyncTask 活动记录到 Internet 上的服务器,因此在后台执行此操作是有意义的.
  • Update: In response to a comment, to emphasize that this could be a valid use of AsyncTask.get(), the following is possible:

    • There could be AsyncTasks that get initiated from the UI thread, which might involve communicating over the internet, e.g. loading a web page, or communicating with a server. Whatever the results of the AsyncTask are, some (or all) of the results are needed to update the screen. Hence an AsyncTask with its doInBackground followed by onPostExecute on the UI thread makes sense.
    • Whenever the UI thread initiates an AsyncTask, it places the AsyncTask object in a queue, for additional processing by a separate background thread once the results are available.
    • For each AsyncTask in the queue in turn, the background thread uses AsyncTask.get() to wait for the task to finish, before doing the additional processing. One obvious example of additional processing could simply be logging all such AsyncTask activities to a server on the internet, so it makes sense to do this in the background.
    • 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(),因为它会导致用户界面冻结,直到结果可用.但是,对于需要隐身的应用程序,这可能正是所需要的.那么以下情况如何:詹姆斯邦德闯入Le Chiffre 并且只有几分钟的时间从恶棍的手机中提取所有数据并安装监控病毒.他安装了 Q 提供的应用程序并开始运行,但他听到有人来了,所以他必须躲起来.Le Chiffre 进入房间并拿起手机拨打电话.有几秒电话似乎有点反应不过来,突然电话就醒了,他想也没想就拨通了电话.当然,无响应的原因是 Q 的应用正在运行.它有各种任务要做,其中一些任务需要按特定顺序完成.该应用程序使用两个线程来完成这项工作,即 UI 线程本身和处理 AsyncTask 的单个后台线程.UI 线程对所有任务进行全面控制,但由于某些任务需要在其他任务之前完成,因此应用程序中存在 UI 线程在等待时使用 AsyncTask.get() 的点要完成的后台任务:-).

      Update2. Another possible valid use of AsyncTask.get() has occurred to me. The standard advice is not to use AsyncTask.get() from the UI thread, because it causes the user interface to freeze until the result is available. However, for an app where stealth is needed, that may be exactly what is required. So how about the following situation: James Bond breaks into the hotel room of Le Chiffre and only has a couple of minutes to extract all the data from the villian's phone and install the monitoring virus. He installs the app provided by Q and starts it running, but he hears someone coming so he has to hide. Le Chiffre enters the room and picks up his phone to make a call. For a few seconds the phone seems a bit unresponsive, but suddenly the phone wakes up and he makes his phone call without further thought. Of course, the reason for the unresponsiveness was the fact that Q's app was running. It had various tasks to do, and some of them needed to be done in a particular order. The app used two threads to do the work, namely the UI thread itself and the single background thread that processes AsyncTasks. The UI thread was in overall control of all the tasks, but because some tasks needed to be done before other tasks, there were points in the app where the UI thread used AsyncTask.get() while waiting for the background task to finish :-).

      这篇关于AsyncTask 的 get() 方法:是否有任何场景它实际上是最佳选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆