14

在 Java 中,我已经习惯使用Futures. 现在我正在研究 Android,它AsyncTask实现了几乎所有相同的方法并涵盖了相似的生命周期。但是,如果我想保持一致并在我的代码中使用 Future,我必须将 AsyncTask 包装在一个愚蠢的包装器中,因为它实际上并没有实现 Future。

他们只需要添加一个isDone()方法,这似乎是微不足道的,然后添加implements Future<Result>. (稍后添加:请参阅下面的答案,了解它的重要性)。

任何 Android 专家都知道一些很好的理由/模糊的错误,它可能导致为什么没有这样做?

4

3 回答 3

8

通过阅读它的实际代码,AsyncTask.java它实际上使用了一个Future任务,然后是更多。AFuture是一个在旅途中异步执行的任务。AnAsyncTask被安排在一个队列上,用于单个(或一组)后台线程。

AnAsyncTask实际上比Future任务更“优越”。Future它在's 的功能之上做了花哨的调度和优化。只需查看 API 介绍级别。Future从 API 1.0 开始就引入了。该AsyncTask对象是在 API 3 中引入的。

AsyncTask 有一个 Future 任务,而不是一个 Future。

异步任务.java

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 */
public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            return postResult(doInBackground(mParams));
        }
    };

    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occured while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}
于 2014-05-15T06:57:03.843 回答
7

我仍然对“为什么”不在未来使用 AsyncTask 的理论原因感兴趣。

但是,为了记录,我最终创建了自己的小类(如下所示)。如果你想要一个 Future,只需扩展它而不是 AsyncTask。IMO,比@Eng.Fouad 在代码中访问私有 mFuture 的想法更简洁。(但感谢这个想法,它让我稍微研究了源代码!)YMMV。

public abstract class FutureAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> implements Future<Result>{

   @Override
   public boolean isDone() {
      return AsyncTask.Status.FINISHED == getStatus();
   }
}
于 2012-07-14T16:53:58.587 回答
1

AsyncTask太简单了。它适用于可能需要几秒钟的短任务,但您不想锁定 UI 线程。如果您确实需要 a Future,那么您的任务可能对 a 来说太复杂AsyncTask了。

您可以AsyncTask通过调用来检查 an 的状态getStatus()Status.PENDING这将返回一个枚举,它可以是Status.RUNNING或之一Status.FINISHED

于 2012-07-14T16:43:07.117 回答