为什么我的处理程序引用了null活动?

时间:2012-09-29 19:57:32

标签: java android static handler weak-references

在我第一次从干净状态进入应用程序后处理程序内部,处理程序处理MSG_PULLED操作,但是对main的引用为null。弱引用不为空。怎么可能发生这种情况?

受到这篇文章的启发:This Handler class should be static or leaks might occur: IncomingHandler

static class MainHandler extends Handler {
    private final WeakReference<MainActivity> wMain; 
    static int angle=0;
    public MainHandler(MainActivity main) {
        super();
        this.wMain = new WeakReference<MainActivity>(main);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivity main = wMain.get();
        int what = msg.what;
        if(what == MSG_PULLED) {
            main.startAnim();
        } 
    }
}

我是如何启动处理程序的:

static MainHandler mainHandler;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainHandler = new MainHandler(this);
        mainHandler.sendEmptyMessageDelayed(MSG_PULLED,500);
    }

1 个答案:

答案 0 :(得分:1)

定期销毁应用中的Activity个实例,并在旋转显示时创建新的实例。

现在应该发生的情况是旧实例是垃圾收集而只存在新实例。如果你保留旧的,你就会造成泄漏。

由于Handler在没有更多消息(?)之前不能被垃圾收集,因此它们可以比创建它们的Activity更长寿,这通常会导致泄漏旧Activity }(直到可以收集Handler),因为Handler通常会强烈引用他们的Activity

代码中的WeakReference方式可以通过保留一个不会阻止垃圾回收的Activity的弱链接来摆脱这个问题。

问题是你以错误的方式使用get()方法:get()只会在原始对象存在时返回它。当它消失时,你得到null。这里:Activity将存在,而它仍然是活动的(由系统确定)。

null也不是一个大问题:当你得到null Activity实例不再存在时(可能是新的实例已经创建,也许它已经完全消失了)所以你不能做任何有用的事了。即使您仍然有参考,动画也不会显示。

基本上就像下面这样,你的问题就解决了

@Override
public void handleMessage(Message msg) {
    super.handleMessage(msg);
    MainActivity main = wMain.get();

    // message arrived after activity death
    if (main == null) return;

    int what = msg.what;
    if(what == MSG_PULLED) {
        main.startAnim();
    } 
}

WeakReference本身(wMain)不为null,因为它本身是作为成员变量的强引用。只是其中的内容可以/将在某个时刻null