android中的Handler和AsyncTask如何防止内存泄露

Handler泄露的关键点有两个:

1). 内部类

2). 生命周期和Activity不一定一致

第一点,Handler使用的比较多,经常需要在Activity中创建内部类,所以这种场景还是很多的。

内部类持有外部类Activity的引用,当Handler对象有Message在排队,则无法释放,进而导致Activity对象不能释放。

如果是声明为static,则该内部类不持有外部Acitivity的引用,则不会阻塞Activity对象的释放。

如果声明为static后,可在其内部声明一个弱引用(WeakReference)引用外部类。
public class MainActivity extends Activity {
private CustomHandler mHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new CustomHandler(this);
}

static class CustomHandlerextends Handler {
// 内部声明一个弱引用,引用外部类
private WeakReference<MainActivity > activityWeakReference;
public MyHandler(MyActivity activity) {
activityWeakReference= new WeakReference<MainActivity >(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MyActivity act= activityWeakReference.get();
if (activityWeakReference!= null && act!= null) {
// ......
}
}
// ... ...
}
}

第二点,其实不单指内部类,而是所有Handler对象,如何解决上面说的Handler对象有Message在排队,而不阻塞Activity对象释放?

解决方案也很简单,在Activity onStop或者onDestroy的时候,取消掉该Handler对象的Message和Runnable。

通过查看Handler的API,它有几个方法:removeCallbacks(Runnable r)和removeMessages(int what)等。
/ 一切都是为了不要让mHandler拖泥带水
@Override
public void onDestroy() {
mHandler.removeMessages(MESSAGE_1);
mHandler.removeMessages(MESSAGE_2);
mHandler.removeMessages(MESSAGE_3);
mHandler.removeMessages(MESSAGE_4);

// ... ...

mHandler.removeCallbacks(mRunnable);

// ... ...
}

上面的代码太长?好吧,出大招:
@Override
public void onDestroy() {
// If null, all callbacks and messages will be removed.
mHandler.removeCallbacksAndMessages(null);
}


AsyncTask的泄露和Handler类似,避免方法如下:
一 适当使用弱引用:
static class DisableChanger extends AsyncTask<Object, Object, Object> {
final PackageManager mPm;
final WeakReference<InstalledAppDetails> mActivity;
final ApplicationInfo mInfo;
final int mState;

DisableChanger(InstalledAppDetails activity, ApplicationInfo info, int state) {
mPm = activity.mPm;
mActivity = new WeakReference<InstalledAppDetails>(activity);
mInfo = info;
mState = state;
}
}

二在activity退出时,终止asynctask任务:
具体退出方法如下:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
// 注意下面这行,如果检测到cancel,则及时退出
if (isCancelled()) break;
}
return totalSize;
}

protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}

protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

官方的例子是很好的,在后台循环中时刻监听cancel状态,防止没有及时退出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值