gpt4 book ai didi

android - 即使 Activity 已销毁,AsyncTask 也不会停止

转载 作者:IT老高 更新时间:2023-10-28 13:15:53 28 4
gpt4 key购买 nike

我有一个 AsyncTaskActivity 开始执行的对象创建并在后台执行操作(最多下载 100 张图像)。一切正常,但有一种我无法理解的特殊行为。
例如:当安卓屏幕的方向改变时,Activity被摧毁并再次创造。所以我覆盖了 onRetainNonConfigurationInstance()方法并将所有下载的数据保存在AsyncTask中执行.我这样做的目的是没有AsyncTask每次运行 Activity在方向更改期间被破坏-创建,但正如我在我的日志中看到的那样,以前的 AsyncTask仍在执行。 (虽然数据保存正确)
我什至试图取消AsyncTaskonDestroy() Activity 的方法,但日志仍然显示 AsyncTask作为运行。
这是非常奇怪的行为,如果有人能告诉我停止/取消 AsyncTask 的正确程序,我将不胜感激。 .

最佳答案

@Romain Guy 给出的答案是正确的。不过,我想补充一些信息,并给出一个或 2 个库的指针,这些库可用于长时间运行的 AsyncTask,甚至更多用于面向网络的异步任务。

AsyncTasks 被设计为在后台执行任务。是的,您可以使用 cancel 停止它方法。当你从网上下载东西时,我强烈建议你take care of your thread when it is the IO blocking state .您应该按如下方式组织下载:

public void download() {
//get the InputStream from HttpUrlConnection or any other
//network related stuff
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
//copy data to your destination, a file for instance
}
//close the stream and other resources
}

使用 Thread.interrupted标志将帮助您的线程正确退出阻塞 io 状态。您的线程将对 cancel 的调用响应更快方法。

AsyncTask 设计缺陷

但是如果您的 AsyncTask 持续时间过长,那么您将面临 2 个不同的问题:
  • Activity 与 Activity 生命周期的联系很差,如果您的 Activity 终止,您将无法获得 AsyncTask 的结果。确实,是的,您可以,但这将是艰难的方式。
  • AsyncTask 没有很好的文档记录。 asynctask 的天真但直观的实现和使用可能会迅速导致内存泄漏。

  • RoboSpice ,我想介绍的库,使用后台服务来执行这种请求。它是为网络请求而设计的。它提供了附加功能,例如请求结果的自动缓存。

    这就是 AsyncTasks 对长时间运行的任务不利的原因。以下推理改编自 RoboSpice motivations 的摘录:解释为什么使用 RoboSpice 满足 Android 平台需求的应用程序。

    AsyncTask 和 Activity 生命周期

    AsyncTask 不遵循 Activity 实例的生命周期。如果您在 Activity 中启动 AsyncTask 并旋转设备,则 Activity 将被销毁并创建一个新实例。但是 AsyncTask 不会死。它将继续存在,直到完成。

    当它完成时,AsyncTask 不会更新新 Activity 的 UI。事实上,它更新了 Activity 的前一个实例
    不再显示。这可能会导致 java.lang.IllegalArgumentException: View not attach to window manager 类型的异常,如果您
    例如,使用 findViewById 来检索 Activity 内的 View 。

    内存泄漏问题

    创建 AsyncTasks 作为 Activity 的内部类非常方便。由于 AsyncTask 需要操作 View
    当任务完成或正在进行时,使用 Activity 的内部类似乎很方便:内部类可以
    直接访问外部类的任何字段。

    尽管如此,这意味着内部类将在其外部类实例上持有一个不可见的引用:Activity。

    从长远来看,这会产生内存泄漏:如果 AsyncTask 持续很长时间,它会保持 Activity “活着”
    而 Android 想摆脱它,因为它不能再显示。 Activity 不能被垃圾收集,这是一个中心
    Android 在设备上保留资源的机制。

    你的任务进度将会丢失

    您可以使用一些变通方法来创建长时间运行的异步任务并根据 Activity 的生命周期管理其生命周期。您可以 cancel the AsyncTask in the onStop method of your activity或者你可以让你的异步任务完成,而不是丢失它的进度和 relink it to the next instance of your activity .

    这是可能的,我们在 RobopSpice 中展示了它的动机,但它变得复杂并且代码不是真正通用的。此外,如果用户离开 Activity 并回来,您仍然会失去任务的进度。加载器也会出现同样的问题,尽管它与上面提到的带有重新链接解决方法的 AsyncTask 更简单。

    使用 Android 服务

    最好的选择是使用服务来执行长时间运行的后台任务。而这正是 RoboSpice 提出的解决方案。同样,它是为网络设计的,但可以扩展到非网络相关的东西。这个库有一个 large number of features .

    借助 infographics,您甚至可以在不到 30 秒的时间内了解它。 .

    将 AsyncTasks 用于长时间运行的操作确实是一个非常糟糕的主意。然而,它们适用于短暂的生命周期,例如在 1 或 2 秒后更新 View 。

    我鼓励您下载 RoboSpice Motivations app ,它确实深入解释了这一点,并提供了执行某些网络相关内容的不同方法的示例和演示。

    如果您正在为非网络相关任务(例如没有缓存)寻找 RoboSpice 的替代方案,您还可以查看 Tape .

    关于android - 即使 Activity 已销毁,AsyncTask 也不会停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2531336/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com