【问题标题】:Calling post on a static handler within android activity在 android 活动中调用静态处理程序上的 post
【发布时间】:2017-08-11 07:52:56
【问题描述】:

根据this 文章,我在 Activity 类中修改了我的处理程序,如下所示:

private static class ActivityHandler extends Handler
{
    private final WeakReference<MyActivity> mActivity;

    public ActivityHandler(MyActivity activity)
    {
        mActivity = new WeakReference< MyActivity >(activity);
    }

    public final MyActivity getActivity()
    {
        return mActivity.get();
    }
}

处理程序已初始化:

ActivityHandler handler = new ActivityHandler(this);

但是,在我的活动逻辑的几个点中,我必须在这个处理程序上调用 post。所以不要这样:

handler.post(new Runnable()
        {
            @Override
            public void run()
            {
                setSomeProperties();
            }
        });

我现在这样做:

handler.post(new Runnable()
        {
            @Override
            public void run()
            {
                MyActivity activity = handler.getActivity();
                if (activity != null)
                {
                    activity.setSomeProperties();
                }
            }
        });

不管在我运行应用程序并检查 hprof 文件是否有泄露的活动时发生了这种变化,我仍然会被指向 handler.post(new Runnable()) 行。我做错了什么?

附言我已经看到许多在处理程序上覆盖 handleMessage 的示例,但是,我无法与我的案例建立联系并使用它。

【问题讨论】:

    标签: java android memory-leaks static inner-classes


    【解决方案1】:

    您正在创建Runnable,它是您的Activity 中的一个匿名类,并且匿名类包含对绑定Activity 的隐式引用。

    Alex Lockwood 在同一篇文章中也谈到了这一点:

    修复当我们实例化匿名时发生的内存泄漏 可运行类,我们将变量设为类的静态字段 (因为匿名类的静态实例不包含隐式 引用他们的外部类)

    解决这个问题(来自同一篇文章):

      /**
       * Instances of anonymous classes do not hold an implicit
       * reference to their outer class when they are "static".
       */
      private static final Runnable sRunnable = new Runnable() {
          @Override
          public void run() { /* ... */ }
      };
    

    但是,我想说,如果 Runnable 不会超过 Activity 的生命周期(即,如果 Activity 被销毁,它将被销毁),则无需将其更改为静态字段。

    来自同一篇文章:

    避免在活动中使用非静态内部类,如果 内部类可能比活动的生命周期更长。

    文章 cmets 部分的另一个解决方案:

    除了将 Runnable 设为静态之外,您还可以只持有一个 (非静态)引用它并调用 onDestroy() 中的 mHandler.removeCallbacks(mRunnable)。

    【讨论】:

    • 非常感谢您。那么在 sRunnable 的 run 方法中,我将如何调用非静态的 setSomeProperties()?
    • 类似于Handler,您可以创建自己的Runnable 类,继承自Runnable,并将Activity 实例放在WeakReference 中。现在您可以使用Activity 实例调用setSomeProperties()。或者文章的 cmets 部分中建议的其他解决方案是在 onDestroy()onDestroy() 中调用 mHandler.removeCallbacks(mRunnable) Activity 而不是将 Runnable 设为静态。你也可以这样做。
    • 再次感谢,这对您很有帮助。
    猜你喜欢
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多