Android:从静态 Handler 类调用非静态方法

Posted

技术标签:

【中文标题】Android:从静态 Handler 类调用非静态方法【英文标题】:Android: Calling non-static methods from a static Handler class 【发布时间】:2012-08-03 10:07:42 【问题描述】:

鉴于此代码:

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;
        
    

【问题讨论】:

***.com/q/11407943/844882 @Alex Lockwood 提供的链接指向另一个来自 Romain Guy 的链接,它帮助我理解了弱引用:静态与非静态内部类 link。我可以回答我自己的问题,但我还不能发布。 我回答了这个问题(因为你显然还不能发布它......):P 【参考方案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

【讨论】:

以上是关于Android:从静态 Handler 类调用非静态方法的主要内容,如果未能解决你的问题,请参考以下文章

Android Threading:这个 Handler 类应该是静态的,否则可能会发生泄漏[重复]

静态与非静态的异同

2020-8-11

面向对象中静态方法和属性的理解

从Android Handler内部类到WeakReference的知识关联

android handler 调用原理