在 android activity 中的静态处理程序上调用 post

Calling post on a static handler within android activity

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

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);

但是,在我的 activity 逻辑的几个点中,我必须在此处理程序上调用 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()) 行。我做错了什么?

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

您正在创建 Runnable,它是您 Activity 中的匿名 class,并且匿名 class 持有对绑定 Activity 的隐式引用。

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

To fix the memory leak that occurs when we instantiate the anonymous Runnable class, we make the variable a static field of the class (since static instances of anonymous classes do not hold an implicit reference to their outer class)

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

  /**
   * 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 被销毁就会被销毁),则无需更改那到静态字段。

来自同一篇文章:

Avoid using non-static inner classes in an activity if instances of the inner class could outlive the activity’s lifecycle.

文章评论区的另一种解决方案:

Instead of making the Runnable static, you could also just hold a (non-static) reference to it and call mHandler.removeCallbacks(mRunnable) in onDestroy().