是的,如果此示例将 a 保留Message
在队列中,则会导致泄漏。但这不是一个非常严重的泄漏,因为它通常仅限于相当短的时间。
但是有一种相当简单的方法可以防止泄漏:
将以下两个类放入您的项目中
/** Callback that decouples the wrapped Callback via WeakReference */
public class SafeCallback implements Handler.Callback {
private final WeakReference<Handler.Callback> mCallback;
public SafeCallback(Handler.Callback callback) {
mCallback = new WeakReference<Handler.Callback>(callback);
}
@Override
public boolean handleMessage(Message msg) {
Handler.Callback callback = mCallback.get();
if (callback != null)
return callback.handleMessage(msg);
// else warn, return true, ..?
return false;
}
}
/** replacement for anonymous inner Handler implementations */
public abstract class SafeHandler implements Handler.Callback {
@Override
public abstract boolean handleMessage(Message msg);
public final Handler get() {
return new Handler(new SafeCallback(this));
}
public final Handler get(Looper looper) {
return new Handler(looper, new SafeCallback(this));
}
}
现在您几乎可以像以前一样使用Handler
/Callback
了,但它不再泄漏。
所以要么喜欢
public class TestActivity extends Activity {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new SafeHandler() { // << instead of new Handler() {
@Override
public boolean handleMessage(Message msg) {
// handle message
return false;
}
}.get(); // << Notice this added .get()
}
}
或喜欢
public class TestActivity2 extends Activity implements Handler.Callback {
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler(new SafeCallback(this)); // << wrapped in SafeCallback
}
@Override
public boolean handleMessage(Message msg) {
// handle message
return false;
}
}
泄漏问题Handler
是每个Message
/ Runnable
(实际上被包裹在 a 中Message
)都知道它的目标,即对Handler
or有一个硬引用Callback
。如果该目标是一个非静态内部类,它将隐含对外部类的硬引用,该外部类通常是一个Activity
.
这意味着只要您的Messages
排队Handler
,您的整体Activity
就不能被垃圾收集。
为了解决这个问题,必须打破从Message
to的硬引用链。Activity
该类SafeCallback
通过只WeakReference
对您的Activity
.
这意味着,Message
现在有一个硬引用,SafeCallback
但那里的部分绑定现在可以被垃圾收集。如果发生这种情况,结果会Handler.Callback callback = mCallback.get();
被简单地丢弃。反正没有更有用的目标了。它仍在泄漏自身,但这是一个几乎是空的类,因此不会导致问题。null
Message
SafeCallback