一般我们在使用handler时,直接回书写匿名内部类或者如下方式,原则上讲是不对的。可能会造成内存泄露,发生OOM异常。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// handler拿到消息调用分发消息和处理消息
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Toast.makeText(MainActivity.this,"我是主线程的吐司",Toast.LENGTH_SHORT).show();
}
};
downloadPicture();
}
在主线程中
Toast.makeText(MainActivity.this,"我是主线程的吐司",Toast.LENGTH_SHORT).show();
引起内存泄露的原因:
当应用启动时,系统自动创建主线程Looper和LooperQueue,所以一旦消息队列中有消息,与消息绑定的主线程handler就一直处于执行过程中,那么在hanldeMessage中所引用的MainActivity就不能被回收掉掉,那么MainActivity中的资源一直被占用,由此可引发内存泄露问题。
解决第一步,把MainActivity作为context引用传递过来,修改代码如下:
自定义MyHandler把Context作为构造函数传递进来
static class MyHandler extends Handler{
private Context mContext;
public MyHandler(Context context){
this.mContext = context;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// handler拿到消息调用分发消息和处理消息
mHandler = new MyHandler(this){
@Override
public void handleMessage(Message msg) {
Toast.makeText(this.mContext,"我是主线程的吐司",Toast.LENGTH_SHORT).show();
}
};
downloadPicture();
}
但是仍然存在上述问题,修改两点,一是改为静态内部类,不持有外部类的引用;二是将mContext对象设为软引用对象,当内存不足时可以被回收,从而避免了内存大量被占用,造成内存泄露,甚至oom问题。
//静态内部类不持有外部类的引用
static class MyHandler extends Handler{
//将对象mContext作为软引用对象,mContext当内存不足时就会被回收。
SoftReference<Context> mContext ;
public MyHandler(Context context){
if(context!=null) {
mContext = new SoftReference<Context>(context);
}
}
}
观看详细信息,请看链接
http://www.jb51.net/article/120627.htm