防侧漏之弱引用的使用
来源:互联网 发布:linux的用户组是什么 编辑:程序博客网 时间:2024/05/17 07:41
本文依然基于github上的开源框架为基础,看过之前发的 最新Retrofit + RxJava + MVP 那篇blog的讲述,应该明白框架里面的大概,一步步兑现之前的承诺,会写上十篇左右的帖子来讲解里面的要点和难点,今天主要讲述的是baseActivity里面的WeakReference< BaseActivity >。
最初入行的时候,使用handler一般都是如下方式:
private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); /** * 各种操作 */ } };
先说下此处的问题,首先,系统会有警告,This Handler class should be static or leaks might occur,大致意思就是说:Handler类应该定义成静态类,否则可能导致内存泄露,因为非静态内部类隐式自动持有外部类的强引用,而静态内部类不会引用外部类对象,目前只需要记住这句话,说到根本原因就牵扯到jvm,这块日后会单独拿出来写一个模块。
再者,这样写的话,如果有一个超生命周期的逻辑,则会出现内存泄漏,百说不如贴上代码:
private void test() { handler.sendMessageDelayed(Message.obtain(), 60000); finish(); }
当Android应用启动的时候,会先创建一个UI主线程的Looper对象,同时会创建一个MessageQueue,Looper循环遍历,把MessageQueue中的message一个一个取出来处理,处理结束后并不会销毁(这和java中消息机制不同,java中处理完便会自动销毁,等待回收),而是等待后续传来的message,只要Handler发送的Message尚未被处理,则该Message及发送它的Handler对象将被线程MessageQueue一直持有,上述代码是activity在finish一分钟后才收到信息,此时的activity中的handler还在被强引用,当这个activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的message持有handler实例的引用,handler又持有activity的引用,所以导致该activity的内存资源无法及时回收,引发内存泄漏,关于handler这块,之前一篇android之handler的刨根问底 进行了详细叙述,有兴趣可以看下。
为何使用弱引用
对于强、软、弱、虚四大引用,之前在简述图片加载框架有过讲述并有代码实例,此处不重复贴代码,对于弱引用,指的是当垃圾回收器扫描到此处垃圾,无论内存是否充足,都会回收,功能上和软引用如出一辙,和软引用最大的不同就是软引用是在内存不足的时候,gc扫描到才会回收此处内存。此处使用弱引用比软引用更加合理,虽然软引用同样可以解决因为强引用导致内存无法回收的问题,但有个前提条件就是需要内存不足的时候才可以,这就没有弱引用来得实在。
改进后的代码如下:
/** * Created by Zero on 2017/7/20. */public abstract class BaseActivity<Pre extends BasePresenter> extends AppCompatActivity implements OnClickListener { private static final String DIALOG_LOADING = "DialogLoading"; private boolean mVisible; private LoadingDialogFragment waitDialog = null; protected Pre presenter; protected final Handler mHandler = new MyHandler(this); private BroadcastReceiver receiver; private IntentFilter filter; private static class MyHandler extends Handler { private final WeakReference<BaseActivity> mActivity; private MyHandler(BaseActivity activity) { mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { if (mActivity.get() != null) { requestOver(msg); } } } /*****************省略一些不相关代码*****************/ @Override protected void onDestroy() { super.onDestroy(); /** * 移除mHandler */ mHandler.removeCallbacksAndMessages(null); if (receiver != null) { LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); } }}
为了避免一些handler拖泥带水,onDestroy方法中对mHandler进行removeCallbacksAndMessages(null)处理,便于mHandler和activity及时被回收。
项目已上传,戳此进入github。
- 防侧漏之弱引用的使用
- Android开发优化之的强引用、软引用、弱引用的使用
- foreach之引用&的使用
- 强引用,软引用,弱引用,虚引用的使用
- Java 强引用 软引用 弱引用的使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- Android性能提升之强引用、软引用、弱引用、虚引用使用
- 学习笔记之引用的使用
- Java 7之基础 - 强引用、弱引用、软引用、虚引用(总结的很好)
- Android 软引用和弱引用的使用分析
- 稻草人的程序之路--函数参数中非引用,引用和const限定符的使用.
- 初识ExtJS---之使用Extjs框架引用的路径问题
- 并行处理之引用计数与状态的使用
- android之BaseAdapter的使用,加深引用对象理解
- opencv Rodrigues函数调用问题
- Python类变量和成员变量使用中有哪些注意事项?
- 集合的划分(重复状态的消除)
- Rabbitmq java client编译
- 内部类
- 防侧漏之弱引用的使用
- 求1-100之间6的倍数的个数,并把能被6整除的数存入数组中
- Python 版本切换pyenv常用命令
- Oracle数据的运算符-yellowcong
- c++ winpcap开发(10)
- 简单的单例模式
- 【每日一题-9】层序遍历与N!后的0的个数
- CodeForces
- C的链表-简单介绍