【问题标题】:Design pattern for modular AsyncTask in AndroidAndroid中模块化AsyncTask的设计模式
【发布时间】:2015-05-19 00:04:17
【问题描述】:

我在 Android 中使用 AsyncTask 已有一段时间了。我喜欢它,因为您可以在后台线程上异步运行您想要的任何任务(任务是指代码块)。

一开始,每次任务应该异步运行和/或在后台线程上运行时,我都会将其代码捆绑到 AsyncTask 的扩展中。我有时需要链接多个这些任务(一个取决于另一个的结果)并在AsyncTask.onPostExecute(T data) 中调用下一个(一旦执行完成),但现在我觉得我的代码被太多样板代码(AsyncTask骨架)和连续任务的耦合。

最重要的是,我的 AsyncTask 有时是从另一个 AsyncTask 启动的,Android 可能会抱怨。例如,如果我想在前/后执行中显示一些元素,那么在嵌套调用时这将是一个问题。

特别是,我正在寻找一种方法来模块化地选择一个任务应该同步/异步、顺序/并行还是与另一个一起运行。到目前为止,我的选择是有一个简单的接口Task 期望实现execute(T data) 方法。然后我可以捆绑其中的一个或多个,按顺序或并行运行,如以下块中所定义:

public doMultipleActions() {
  runTask(new MyFirstParallelTask(myFirstData)); // running asynchronously in parallel the first task
  runTask(new MySecondParallelTask(mySecondData)); // running asynchronously in parallel the second task

  runTask(new MyFirstSequentialTask(myThirdData, new MySecondSequentialTask(myFourthData, new DummyCallback()))); // running asynchronously sequentially the third and fourth tasks
}

runTask(Task t) 会将Task.execute(T data) 的代码运行到AsyncTask.doInBackground(T... data) 代码块中。顺序任务还期望在 AsyncTask.onPostExecute(T data) 代码块中执行另一个任务。

我查看了多个类似的问题:Can I chain async task sequentially (starting one after the previous asynctask completes)AsyncTask chaining in Activity (callback?)How to avoid chaining several AsyncTask calls?,最接近我的问题但我找不到任何有用的东西,即使我不认为我是唯一一个处理这个问题的人.

在Android中AsyncTask的模块化使用是否有更好的方法、预期的方法,甚至是设计模式?

【问题讨论】:

    标签: java android design-patterns android-asynctask


    【解决方案1】:

    通过使用executeOnExecutor 和参数AsyncTask.SERIAL_EXECUTORAsyncTask.THREAD_POOL_EXECUTOR,可以以串行或并行方式运行多个AsyncTask。

    如果您期望具有等待机制的结果(例如等待任务完成并返回结果),那么更好的方法是使用 Future.一种这样的实现是FutureTask,它依赖于这样的 Callable:

    ExecutorService pool = Executors.newFixedThreadPool(poolSize);
    FutureTask<String> future = new FutureTask(new Callable() {
        public String call() {
            ...
        return res;
    });
    executor.execute(future);
    
    String res = future.get(); 
    

    最后一行将阻塞操作,直到 Callable inside 返回其 String 结果。事实上,你甚至可以设置一个超时来完成它。

    请记住,AsyncTask 不仅执行异步操作。它还在后台线程上执行其进程。因此,您仍然可以使用 AsyncTask(或 Thread)来执行同步操作,否则会阻塞 UI。

    【讨论】:

    • 感谢您的建议,这很有趣,但我看不出它是如何回答问题的(这更多是关于 AsyncTask 的批处理而不是异步任务)。我可以改进我的问题。还有一件事,在一个AsyncTask 中运行多个任务不等于多个AsyncTask,通常多个AsyncTask 可以并行运行。
    • 首先 AsyncTask 代表 Asynchronous 任务。其次,您正在寻找一种方法来选择一个任务是异步运行、一个接一个地运行还是与另一个任务一起运行,但您似乎只有 AsyncTask 可供您使用。事实上,链式 AsyncTask 在技术上是形成一个同步过程(下一个 AsycTask 等待前者)。所以我推断你正在寻找一种同步的方式来运行一个进程。
    • 我明白了,你是对的。这不是我所期望的,但我会阅读文档以了解如何整合它。谢谢
    • 公平地说,我重读了你的问题,我觉得你想严格按照AsyncTask 来做。我为此更新了我的答案。可以使 AsyncTask 串行或并行运行。如果您想这样做,那么AsyncTaskexecuteOnExecutor 就可以了。关于可以同时运行的最大 AsycTask 数量以及不同 API 上的不同默认行为有一些注意事项。事实上,如果你运行 ICS,那么它默认是串行的。因此,如果我只寻求结果,我会使用 Future,如果想要同时执行后台任务和更新 UI,我会使用 AsyncTask。
    • 是的,我不是要求另一个工具做一些接近 AsyncTask 的事情,AsyncTask 适合我,而是如何模块化地操作这个概念。您的回答让我意识到我的问题并没有集中在正确的事情上(包装,而不是 AsyncTask 工具)。我还没有时间尝试您的解决方案,我会尽快尝试。
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多