14.Android 控制Handler内存泄露 技巧
2015-09-21 13:47
387 查看
14.Android 控制Handler内存泄露 技巧
Android 控制Handler内存泄露 技巧Handler 警告
Handler 内存泄露缘由
解决思路
Handler 通用模板
Handler 警告
In Android, Handler classes should be static or leaks might occur, Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class这是在用Handler不加
static都会出现的一个警告。
Handler 内存泄露缘由
一个Android应用启动的后,都会创建一个主UI线程,再为这个主UI线程提供一个Looper对象,这样所有的Android框架的事件(Activity的生命周期方法调用和事件)都是放入消息中,再加入Looper处理的MessageQueue中。也就是说主线程的Looper生命周期是与Android应用一样长的。每次在
Handler.sendMessage(message)的时候,实际已经发送的message已经包含了改Handler的引用。因为在只有这样Looper才能调用处理改message的handler,进而走到
handler.handleMessage(Message msg)中,不然,你想,我发一个message,Looper怎么知道message处理过后告诉哪个Handler执行
handler.handleMessage(Message msg)。
非静态的内部类和匿名的内部类都会隐式地持有了它的对应外部类的引用。静态的内部类不会持有外部类的引用。
出现泄漏的场景:假如我的Handler里做了很多耗时的工作,在
Activity.finish()后Handler还在忙碌的话,就一直持有该Activity的引用,Activity无法回收,进行导致Activity持有的很多资源都无法回收,就会出现Handler的内存泄漏
解决思路
解决思路基本上是:不用非静态的Handler,继承Handler的时候,可以选择独立出一个Handler类
静态Handler
以上,这两种方法。因为静态的内部类不会持有外部类(Activity)的引用,所以不会导致外部类实例的内存泄露。
在Android中很多的内存泄露都是由于在Activity中使用了非静态内部类导致的,所以使用时要非静态内部类时要格外注意,如果实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。
Handler 通用模板
private TextView handlerTV; private static final int HANDLER_SUCCESS = 206; private static class RefreshHandler extends Handler { private final WeakReference<RefreshUIActivity> mActivity; public RefreshHandler(RefreshUIActivity activity) { mActivity = new WeakReference<>(activity); } /** * Subclasses must implement this to receive messages. * * @param msg */ @Override public void handleMessage(Message msg) { RefreshUIActivity activity = this.mActivity.get(); if (activity != null) { switch (msg.what) { case HANDLER_SUCCESS: { activity.handlerTV.setText("success"); break; } } } } } private final RefreshHandler refreshHandler = new RefreshHandler(RefreshUIActivity.this); private final Runnable mRunnable = new Runnable() { @Override public void run() { Message message = RefreshUIActivity.this.refreshHandler.obtainMessage(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } message.what = HANDLER_SUCCESS; refreshHandler.sendMessageDelayed(message, 2000); } }; private final Thread mThread = new Thread(mRunnable);
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories