【问题标题】:Android: Calling non-static methods from a static Handler classAndroid:从静态 Handler 类调用非静态方法
【发布时间】:2023-03-15 20:15:01
【问题描述】:

鉴于此代码:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

public static final int MESSAGE_NOT_CONNECTED = 1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

// -------------------------------------------------
public final void setStatus(int Rid) {
    final ActionBar actionBar = getActionBar();
    actionBar.setSubtitle(Rid);
}

// -------------------------------------------------
static Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case MESSAGE_NOT_CONNECTED:
            setStatus(R.string.title_not_connected);
            break;
        }
    }
}
}

我收到编译错误:无法对非静态方法 setStatus(int) 进行静态引用 ...

这是有道理的,因为 setStatus() 中的 getActionBar() 是一个非静态方法。

由于警告,我将 Handler 类设为静态:此 Handler 类应该是静态的,否则可能会发生泄漏。

问题:如何从静态处理程序中正确访问 setStatus() 方法?

编辑:新的处理程序代码就是答案。

static class hHandler extends Handler {
    private final WeakReference<MainActivity> mTarget;
    hHandler(MainActivity target) {
        mTarget = new WeakReference<MainActivity>(target);
    }

    @Override
    public void handleMessage(Message msg) {
        MainActivity target = mTarget.get();
        If(target == null) {
             return;
        }
        switch (msg.what) {
        case MESSAGE_NOT_CONNECTED:
            target.setStatus(R.string.title_not_connected);
            break;
        }
    }
}

【问题讨论】:

  • @Alex Lockwood 提供的链接指向另一个来自 Romain Guy 的链接,它帮助我理解了弱引用:静态与非静态内部类 link。我可以回答我自己的问题,但我还不能发布。
  • 我回答了这个问题(因为你显然还不能发布它......):P

标签: android handler android-actionbar


【解决方案1】:

尝试使用WeakReference,如article 中所述。

【讨论】:

  • 这就是答案。我用更改编辑了原始帖子。感谢您的发帖,亚历克斯。
  • @Alex Lockwood 那篇文章很好,但它没有解释如何从静态处理程序中获取上下文。我正在使用 Toast.makeText(getApplicationContext(), dataString, Toast.LENGTH_SHORT).show();既然 Handler 是静态的,那么 getApplicationContext() 就没有意义了。如果这很重要,我的处理程序在服务中。
  • @DavidDoria 给Handler 一个构造函数,它接受Context 作为参数,然后持有对该Context 的弱引用。
【解决方案2】:

由于您现在使用的是WeakReference,因此mTarget.get() 可能会返回null。在您编辑的代码中,您没有在执行 target.setStatus(R.string.title_not_connected) 之前检查 target 是否为 null。因此,如果弱引用对象已被 GC 处理,这可能会抛出 NullPointerException。

【讨论】:

    【解决方案3】:

    在我调用的活动的 onDestroy 方法中:

    this.myHandler.removeCallbacksAndMessages(null);
    

    这并没有消除“这个处理程序类应该是静态的,否则可能会发生泄漏”的警告,但我相信它会破坏消息从而阻止泄漏。我的处理程序类是我活动的内部非静态类。我的活动有一个 MyHandler myHandler 的实例。

    当我这样做时,不会调用处理程序的 handleMessage 方法,我认为这意味着包含处理程序的消息已被销毁,其中包含对活动的引用。我对 cme​​ts 持开放态度,因为我没有使用任何泄漏测试工具对其进行测试。这是我复制这个想法的地方:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html 回答者:Cyril 2013 年 1 月 15 日上午 7:50

    【讨论】:

      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-20
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多