在之前的项目中,Handler也使用,但往往是这么用的:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message message = new Message();
message.what = 1;
mHandler.sendMessageDelayed(message,10*60*1000);
}
今天听同事,说这样的会造成内存泄漏,建议用静态内部类,并弱引用,判断其Acitivity,自己也查询了百度相关资料,写下这篇,提醒自己。
造成内存泄漏的原因:非静态内部类会隐性地持有外部类的引用,二静态内部类则不会。在上面的代码中,Message在消息队列中延时了10分钟,然后才处理该消息。而这个消息引用了Handler对象,Handler对象又隐性地持有了Activity的对象,当发生GC是以为 message – handler – acitivity 的引用链导致Activity无法被回收,所以发生了内存泄露的问题。
当然简单的做法,可以在ondestroy()
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
建议ondestory() 操作的同时,也改下handler
private NoLeakHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new NoLeakHandler(this);
Message message = Message.obtain();
message.what = 1;
mHandler.sendMessageDelayed(message,10*60*1000);
}
static class NoLeakHandler extends Handler {
private WeakReference<Activity> mActivity;
public NoLeakHandler(Activity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mActivity.get();
if (activity != null) {
switch (msg.what) {
}
}
}
}
通过弱引用Activity,判断Activity 的是否还存在,处理事情。
另外,新的代码将Message message = new Message();
改成了 Message message = Message.obtain();
因为这种可以避免重复创建Message对象
Message 的使用有三种:
1.Message msg = new Message();
2.Message msg2 = Message.obtain();
3.Message msg1 = handler1.obtainMessage();
- 这种就是直接初始化一个Message对象,没有什么特别的
2.第二种,看源码
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
从整个Messge池中返回一个新的Message实例,通过obtainMessage能避免重复Message创建对象。
- 第二种跟第三种其实是一样的,都可以避免重复创建Message对象,所以建议用第二种或者第三种任何一个创建Message对象。
所以,之后使用Handler 时,多加注意内存泄漏,和避免Message的重复创建。