在我第一次从干净状态进入应用程序后,在处理程序内部,处理程序处理MSG_PULLED操作,但对main的引用为null。弱引用不为null。这怎么可能发生?
受这篇文章的启发:这个Handler类应该是静态的,否则可能会发生泄漏: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);
}
应用程序中的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
。