【问题标题】:Android - Do I have to have WeakReference for inner class AsyncTask?Android - 我是否必须为内部类 AsyncTask 提供 WeakReference?
【发布时间】:2013-10-23 20:18:27
【问题描述】:

假设我在 Activity 类中有一个内部类 AsyncTask。 我必须在这个 AsyncTask 中有弱引用吗?

另外,我是否必须一直为 AsyncTask 提供弱引用?

最后,如果我将内部类 AsyncTask 声明为静态,是否安全?

【问题讨论】:

    标签: android android-asynctask weak-references


    【解决方案1】:

    是的,如果你的Asynctask是一个内部类,或者只是创建它自己的类,总是声明你的静态类,尽量避免声明为非静态内部类,因为它会造成内存泄漏。 Read here for a more elaborate explanation why you should not do this

    您不想将WeakReference 用于 Asynctask,因为 android 2.3+ 的垃圾收集器非常激进,并且会非常快速地收集所有弱引用。弱引用通常也不是线程的好模式,它更多的是用于内存占用大的对象,如位图(但在 android 中不再是如前所述)。

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

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

    【讨论】:

      【解决方案2】:

      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 传递给构造函数。 (我假设您在构造函数中编写了上面显示的赋值语句。

      【讨论】:

        【解决方案3】:

        如果您出于正确的原因使用WeakReference,那么拥有积极的垃圾收集器应该不会打扰您。

        WeakReference 表示如果没有其他人强烈指向该对象,则您对该对象不感兴趣。

        例如,有一个 AsyncTask 传递一个 ImageView 来加载图像。

        AsyncTask 完成后,如果没有人指向具有强引用的图像视图,则意味着ImageView 不再对用户可见,并且它的视图已被破坏,所以为什么您是否希望引用已从屏幕上移除的视图。

        所以是的,我相信您在 AsyncTask 中的所有引用都应该是弱引用,特别是与 UI“视图、活动”之类的东西相关的引用。

        是的,你应该尽可能将你的内部类声明为static,这样它们就没有对其包含类的隐式引用,这将破坏我们使用WeakReference所做的尝试

        【讨论】:

        • 没有强引用的对象就不能被垃圾回收吗?如果您需要对 asynctask 进行强引用而不是在弱引用中自动收集垃圾,那不是违背了目的吗? WeakRef 通常用于例如缓存,在这里可以得到一个空值,因为你只是重新创建了对象。如果 asynctask 为 null,您必须重新创建整个任务,并且如果您仍然保持强 ref,那么弱引用没有意义,还是我错过了重点?
        • 你完全误解了我的意思,我不是说对 AsyncTask 本身有一个弱引用,我说对异步任务中的对象有一个弱引用,这只是开始。其次,Java 中的线程通常由 JVM 保存和管理,因此如果您启动一个线程或异步任务并且您根本没有对它的引用,它仍然会在内存中,直到它完成它的工作,那么我将被垃圾收集,但之前不会。
        • 如果UI(activity)结束了,就不会有对imageView的强引用->不管是弱引用还是强引用都会被收集,所以我没有得到weak的优势在那种情况下参考。它似乎只会增加复杂性而没有任何好处。
        • 不,如果活动完成并且您可以对 ImageView 进行强引用,则 ImageView 和整个活动[如果 ImageView 附加到活动]将不会被垃圾收集。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-30
        • 2021-08-29
        • 1970-01-01
        • 1970-01-01
        • 2017-10-29
        相关资源
        最近更新 更多