【问题标题】:Which strategy to choose when doing long running tasks on Android?在 Android 上执行长时间运行的任务时选择哪种策略?
【发布时间】:2013-11-03 12:55:27
【问题描述】:

我正在创建一个可以下载大约 30 张图像的应用程序。假设它需要超过 10 秒。我一直在阅读有关 AsyncTask 的信息,我猜它不应该被使用,因为该任务将花费超过几秒钟的时间。

理想情况下,AsyncTasks 应该用于短操作(几秒钟 最多。)如果您需要保持线程长时间运行 时间,强烈建议您使用由提供的各种 API Executor、ThreadPoolExecutor等java.util.concurrent包 和 FutureTask。

查看ASyncTask 的API 时,我发现有些方法可以发布到UI 线程。如果我理解正确的话,更合适的方式来执行长时间运行的任务是使用FutureTask?这意味着我必须自己发布 UI 线程的更新。你用post(Runnable) method of View对吗?

无论我是否走在正确的轨道上,我都可能需要一些指导。

【问题讨论】:

  • 使用 IntentService 或后台服务执行长任务...

标签: java android multithreading android-asynctask


【解决方案1】:

您可以将短操作理解为与您的 Activity 生命周期相关的操作。

您可以使用在 UI 线程上执行的 onProgressUpdate() 回调来更新 UI。

但是,如果您的 Activity 在此过程中暂停,这很可能会崩溃,因此您应该在 onPause() 中使用 task.cancel(true) 取消您的任务;

如果您需要您的任务来维持您的活动,那么您应该使用服务或 ServiceIntent。前者稍微复杂一些,因为您必须管理其生命周期,但提供了更大的灵活性。第二个非常简单,所以我可以在这里举个例子:

public class MyIntentService extends IntentService{

public MyIntentService() {
    super("MyIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
    // Background work in a worker thread (async)

    // You could also send a broadcast if you need to get notified
    Intent broadcastIntent = new Intent();
    broadcastIntent.setAction("whatever");
    LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
}

你可以从你的活动开始

Intent i = new Intent(context, MyIntentService.class);
context.startService(i);

【讨论】:

  • 那么你什么时候使用文档中提到的东西作为 AsyncTask 的替代品,例如 FutureTask、Executors 等?没有提及此事。
  • 我从未在我的 android 项目中使用过 FutureTask。它是一个通用的 java AsyncTask(它不是特定于 Android 的),提供比线程更灵活的接口。我看不到任何使用 FutureTask 应该优先于 AsyncTask(Android 特定)的用例,因为后者提供了一种非常方便的方式来在后台作业之前、期间和之后与 UI 线程进行交互。
  • 我必须同时运行多个操作,这些操作可能会在用户与不同活动交互时执行。我不能使用 Intent 服务,因为运行多个 Intent 服务将一一执行而不是并行执行。使用服务也是一个问题,因为如果 Android 操作系统运行超过 1 分钟而用户未使用应用程序或已将应用程序最小化以在几分钟后返回应用程序,则会将其杀死。你会推荐哪种方法?一个线程?还是别的什么?
【解决方案2】:

AsyncTask 不遵循 Activity 实例的生命周期。如果您在 Activity 中启动 AsyncTask 并旋转设备,则 Activity 将被销毁并创建一个新实例。但是 AsyncTask 不会死。这是建议避免将 AsyncTask 用于长时间运行的任务的原因之一。

我相信在您的情况下,简单的threading 就足够了,因为您只是在下载数据。如果需要更新 UI 元素,也可以使用 Handlers。

编辑:

在 FutureTask 执行其工作期间,您无法更新 UI。 UI 只能在完成工作后更新。

A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask 
implements Runnable, a FutureTask can be submitted to an Executor for execution.

【讨论】:

  • 你可以用 FutureTask 封装 Handlers,这样你就可以用它来更新 UI。
  • 那么我链接到的 post 方法在 View 类中可用呢?
  • 正如我所说,您可以更新 UI,但在 futureTask 检索到所有数据之后。与 AsyncTask 不同,您可以在检索数据时发布进度/更新 UI。
  • 我必须同时运行多个操作,这些操作可能会在用户与不同活动交互时执行。我不能使用 Intent 服务,因为运行多个 Intent 服务将一一执行而不是并行执行。使用服务也是一个问题,因为如果 Android 操作系统运行超过 1 分钟而用户未使用应用程序或已将应用程序最小化以在几分钟后返回应用程序,则会将其杀死。你会推荐哪种方法?一个线程?还是别的什么?
猜你喜欢
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-11
  • 2012-02-22
相关资源
最近更新 更多