一般我們在使用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