Android - 我是否需要在内部类AsyncTask中使用WeakReference?

3

假设我在一个活动类中有一个内部类AsyncTask。 我必须在这个AsyncTask中使用weakReference吗?

此外,我是否必须始终为AsyncTask使用weakReference?

最后,如果我将内部类AsyncTask声明为static,它是安全的吗?

3个回答

2

如果 Asynctask 是一个内部类,你应该始终将其声明为静态的,或者创建一个属于它自己的类。尽量避免声明为非静态内部类,因为这会导致内存泄漏。在这里阅读更详细的解释,为什么你不应该这么做

你不应该使用 WeakReference 来引用 Asynctask,因为 Android 2.3+ 的垃圾回收机制非常积极,会很快回收所有的弱引用。弱引用通常也不是线程的好模式,它更适用于内存占用较大的对象,如位图(但在 Android 中已经改变了,如上所述)。

来自 http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

从 Android 2.3(API 级别 9)开始,垃圾回收器会更积极地回收软/弱引用,这使得它们相当无效。


1
< p > WeakReference 允许 Activity 被垃圾回收,因此您不会出现内存泄漏。

空引用意味着 AsyncTask 不能盲目尝试更新不再连接的用户界面,否则会抛出异常(例如,视图未连接到窗口管理器)。当然,您必须检查 null 以避免 NPE。因此,使用 WeakReference 处理上述情况是一个好习惯。 是的,将内部类声明为 static 是完全安全的。

WeakReference<Activity> weakActivity;

在AsyncTask的某个地方,可能是构造函数或onPreExecute方法中:

weakActivity = new WeakReference<Activity>(activity);

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

在启动 AsyncTask 的活动中,将 this 传递给构造函数。(我假设你在构造函数中编写了上面显示的赋值语句。)

1
如果您使用WeakReference的原因正确,那么有一个积极的垃圾回收器不应该困扰您。 WeakReference意味着如果没有其他人强烈指向它,您对于保留该对象在内存中并不感兴趣。
例如,将ImageView传递给AsyncTask以加载图像。
AsyncTask完成其工作后,如果没有人用强引用指向该图像视图,则表示该ImageView对用户不再可见,其视图已被销毁,那么为什么您可能想要引用已经从屏幕上移除的视图呢?
因此,我认为AsyncTask中的所有引用都应该是弱引用,特别是与UI相关的“视图、活动”之类的东西。
是的,尽可能将内部类声明为静态类,这样它们就不会隐式地引用其包含类,这将破坏我们使用WeakReference所尝试做的事情。

没有强引用的对象不是可以被垃圾回收吗?如果您需要一个强引用来防止异步任务在弱引用中自动垃圾回收,那么这不是违背了初衷吗?WeakRef通常用于例如缓存之类的情况,因为获取null是可以接受的,因为您只需重新创建对象即可。如果asynctask为null,则必须重新创建整个任务,如果仍然保留强引用,则弱引用没有意义,或者我错过了重点? - Patrick
你完全误解了我的意思,我没有说要对AsyncTask本身使用弱引用,我是说要对异步任务内部的对象使用弱引用,这是为了开始。其次,在Java中,线程通常由JVM保留和管理,因此,如果您启动一个线程或异步任务,并且根本没有引用它,它仍将在内存中,直到完成工作,然后才会被垃圾回收,但在此之前不会。 - elmorabea
如果UI(活动)已经完成,那么imageView将不会有强引用->无论是弱引用还是强引用,它都将被收集,因此在这种情况下我没有获得弱引用的优势。它似乎只是增加了复杂性而没有任何收益。 - Patrick
不,如果活动已经完成并且您可以获得 ImageView 的强引用,则 ImageView 和整个活动(如果 ImageView 附加到活动)将不会被垃圾回收。 - elmorabea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接