android 中的 WeakReference/AsyncTask 模式

WeakReference/AsyncTask pattern in android(android 中的 WeakReference/AsyncTask 模式)

本文介绍了android 中的 WeakReference/AsyncTask 模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于 android 中这种简单频繁发生的情况的问题.

I have a question regarding this simple frequently occurring situation in android .

我们有一个 main Activity,我们调用了一个 AsyncTask 以及 mainActivity 的引用,以便 AsyncTask 可以更新 MainActivity 上的视图.

We have a main activity , we invoke an AsyncTask alongwith the reference of the mainactivity , so that that the AsyncTask can update the views on the MainActivity.

我将把事件分解成几个步骤

I will break down the event into steps

  • MainActivity 创建一个 AyncTask ,将其引用传递给它.
  • AysncTask ,开始工作,例如下载十个文件
  • 用户更改了设备的方向.这会导致 AsyncTask 中的孤儿指针
  • 当 AsyncTask 完成并尝试访问活动以更新状态时,由于空指针而崩溃.

上面的解决方法是按照《Pro Android 4》一书的建议,在AsyncTask中保留一个WeakReference

The solution for the above is to keep a WeakReference in the AsyncTask as recommended by the book "Pro Android 4"

WeakReference<Activity> weakActivity;

in method onPostExecute

Activity activity = weakActivity.get();
if (activity != null) {
   // do your stuff with activity here
}

这是如何解决这种情况的?

How does this resolve the situation ?

我的问题是,如果我的 asynctask 正在下载 10 个文件,并且在 5 个文件完成后重新启动该活动(由于方向更改),那么我的 FileDownloadingTask 是否会再次被调用?

My question it , if my asynctask is downloading ten files , and upon completion of 5 the activity is restarted (because of an orientation change) then would my FileDownloadingTask be invoked once again ?.

最初调用的前一个 AsyncTask 会发生什么?

What would happen to the previous AsyncTask that was initially invoked ?

谢谢,对于问题的长度,我深表歉意.

Thank you , and I apologize for the length of the question .

推荐答案

这是如何解决这种情况的?

How does this resolve the situation ?

WeakReference 允许对 Activity 进行垃圾收集,因此您不会有内存泄漏.

The WeakReference allows the Activity to be garbage collected, so you don't have a memory leak.

空引用意味着 AsyncTask 不能 盲目尝试更新不再附加的用户界面,这会引发异常(例如视图未附加到窗口经理).当然,您必须检查 null 以避免 NPE.

A null reference means that the AsyncTask cannot blindly try to update a user-interface that is no longer attached, which would throw exceptions (e.g. view not attached to window manager). Of course you have to check for null to avoid NPE.

如果我的 asynctask 正在下载 10 个文件,并且在 5 个文件完成后重新启动 Activity(由于方向更改),那么我的 FileDownloadingTask 会再次被调用吗?.

if my asynctask is downloading ten files , and upon completion of 5 the activity is restarted (because of an orientation change) then would my FileDownloadingTask be invoked once again ?.

取决于您的实现,但可能是的 - 如果您不刻意做一些事情来使重复下载变得不必要,例如将结果缓存在某处.

Depends on your implementation, but probably yes - if you don't deliberately do something to make a repeat download unnecessary, such as caching the results somewhere.

最初调用的前一个 AsyncTask 会发生什么?

What would happen to the previous AsyncTask that was initially invoked ?

在早期版本的 Android 中,它会一直运行到完成,下载所有文件只是为了将它们扔掉(或者可能缓存它们,具体取决于您的实现).

In earlier versions of Android it would run to completion, downloading all of the files only to throw them away (or perhaps cache them, depending on your implementation).

在较新的 Android 中,我怀疑 AsyncTask 与启动它们的 Activity 一起被杀死,但我怀疑的依据只是内存泄漏RoboSpice(见下文)的演示实际上并没有泄漏到我的 JellyBean 设备上.

In newer Android's I am suspicious that AsyncTask's are being killed along with the Activity that started them, but my basis for suspicion is only that the memory-leak demo's for RoboSpice (see below) do not actually leak on my JellyBean devices.

如果我可以提供一些建议:AsyncTask 不适合执行潜在的长时间运行的任务,例如网络.

If I may offer some advice: AsyncTask is not suitable for performing potentially long running tasks such as networking.

IntentService 是一种更好(而且仍然相对简单)的方法,前提是您可以接受单个工作线程.如果您想控制线程池,请使用(本地)Service - 并注意不要在主线程上工作!

IntentService is a better (and still relatively simple) approach, if a single worker thread is acceptable to you. Use a (local) Service if you want control over the thread-pool - and be careful not to do work on the main thread!

RoboSpice 如果您正在寻找一种在后台可靠地执行网络的方法,那么它看起来不错(免责声明:我没有尝试过;我没有附属).有一个 RoboSpice Motivations 演示应用在 Play 商店中,它解释了为什么您应该通过演示 AsyncTask 可能出错的所有事情来使用它 - 包括 WeakReference 解决方法.

RoboSpice seems good if you are looking for a way to reliably perform networking in the background (disclaimer: I have not tried it; I am not affiliated). There is a RoboSpice Motivations demo app in the play store which explains why you should use it by demo-ing all the things that can go wrong with AsyncTask - including the WeakReference workaround.

另见此线程:是 AsyncTask真的概念上有缺陷还是我只是遗漏了什么?

更新:

我创建了一个 github 项目,其中包含使用 下载的示例IntentService 用于另一个 SO 问题(How to fix android.os.NetworkOnMainThreadException?),但是我认为这在这里也很重要.它还有一个额外的好处,即通过 onActivityResult 返回结果,当您旋转设备时正在运行的下载将传送到重新启动的 Activity.

I created a github project with an example of downloading using IntentService for another SO question (How to fix android.os.NetworkOnMainThreadException?), but it is also relevant here, I think. It has the added advantage that, by returning the result via onActivityResult, a download that is in flight when you rotate the device will deliver to the restarted Activity.

这篇关于android 中的 WeakReference/AsyncTask 模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:android 中的 WeakReference/AsyncTask 模式

基础教程推荐