有篇译文大概这么讲:
dialog也有不寻常的内存泄漏,跟我们常见的handler.removeCallbacks移除runnable(匿名内部类持有了activity/fragment的引用)避免的内存泄漏不太一样。我们都知道常见的泄漏在于handler可能长时间持有了runnable,这个时间超过了activity/fragment的生命周期了,无法释放知道handler不再持有该runnable。
而这个不寻常的泄漏,是这样的(伪代码):
while(true) {
Message msg = next();
...
dispatchMessage(msg);
...
msg.recycle();
}
可以看到代码会在msg.recycle()后回到之前的next()并阻塞等待下一个msg。
泄漏可能这么来了:在dalvik上,或者在Debuggable设置为true的情况下,这段代码在等待下一个msg的时候,上一个msg实际上不会被释放,即便msg内容为空(recycle后内容清空了)。这可以理解对吧,但当这个时候假设有这么一段伪代码:
Message localMsg = Message.obtain();
localMsg.obj = new MyObject();
假设localMsg刚好得到的msg就是上述的空msg,并设置了obj,那么如果next()一直长时间没有message的情况下而你又想要销毁这个MyObject,泄漏就出现了。
可能说完还是有些懵,可以先自行实践一下,完整代码在最下面。也可以跳过实践看下面的译文,不过译文可能比我的还长,看不下去可以直接实践哈哈。
译文地址: