关闭

防侧漏之弱引用的使用

标签: 内存泄漏弱引用WeakReferehandler
3885人阅读 评论(4) 收藏 举报
分类:

本文依然基于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;

    /*****************省略一些不相关代码*****************/

    @Override
    protected void onDestroy() {
        super.onDestroy();
        /**
         * 移除mHandler
         */
        mHandler.removeCallbacksAndMessages(null);
        if (receiver != null) {
            LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
        }
    }
}
/**
 * Created by zero on 2017/7/24.
 */

public class MyHandler extends Handler {
    private final WeakReference<BaseActivity> mActivity;

    /**
     * 从BaseActivity中提取出来,原来是因为内部类会隐式强引用当前类,采用弱引用,避免长生命周期导致内存泄漏
     *
     * @param activity
     */
    public MyHandler(BaseActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        if (mActivity.get() != null) {
            mActivity.get().requestOver(msg);
        }
    }
}

为了避免一些handler拖泥带水,onDestroy方法中对mHandler进行removeCallbacksAndMessages(null)处理,便于mHandler和activity及时被回收。

项目已上传,戳此进入github。

0
2
查看评论

学习笔记:弱引用的使用

弱引用的使用
  • zyjzyj2
  • zyjzyj2
  • 2016-10-04 11:52
  • 140

[Android] Android开发优化之——使用软引用和弱引用

Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。这里重点介绍一下软引用和弱引用。如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象...
  • arui319
  • arui319
  • 2013-01-10 12:49
  • 54239

Java弱引用(WeakReference)的理解与使用

看到篇帖子, 国外一个技术面试官在面试senior java developer的时候, 问到一个weak reference相关的问题. 他没有期望有人能够完整解释清楚weak reference是什么, 怎么用, 只是期望有人能够提到这个concept和java的GC相关. 很可惜的是, 20多...
  • zmx729618
  • zmx729618
  • 2017-01-05 15:20
  • 9576

软引用和弱引用在安卓开发中的使用

用处一:解决Handler可能造成的内存泄露。 原因分析:为什么Handler可能造成内存泄露。 当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用,不然你怎么可能通过Handler来操作Activity中的Vi...
  • chenrushui
  • chenrushui
  • 2016-10-09 18:18
  • 1185

[Android] Android开发优化之——使用软引用和弱引用

转自:http://blog.csdn.net/arui319/article/details/8489451 Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。 这里重点介绍一下软引用...
  • c1163208826
  • c1163208826
  • 2015-09-10 13:58
  • 124

十大名词

10.相当的 赵本山春节晚会的小品,几乎每年都会引爆几句流行语。“相当的”已经成了一个挂在嘴边的形容词,“马甲”也成为网络上的千古绝唱,还将继续唱下去,期待他今年春节晚会的作品,感谢他带给我们的笑声。   9.手榴弹要是一块钱六个,我先扔你一百块钱的 2006年郭德纲带给我们的笑比《无极》...
  • fanhgye
  • fanhgye
  • 2007-01-11 23:43
  • 672

什么是Java的弱引用(Weak Reference)

 之前一直没有接触过弱引用这个概念,今天看到以后觉得挺新鲜,就查了查资料总结一下,希望对大家有所帮助。 要理解弱引用,首先要先了解一下强引用(Strong Reference),  其实我之前也并不了解强引用,虽然天天都在用。举例来说:   ...
  • jinhuiyu
  • jinhuiyu
  • 2009-01-05 07:33
  • 35367

Android开发优化之——使用软引用和弱引用

Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。 这里重点介绍一下软引用和弱引用。 如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收...
  • u014299265
  • u014299265
  • 2016-12-18 13:40
  • 219

使用软引用和弱引用讲解

Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。 如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回...
  • qqmuhua123
  • qqmuhua123
  • 2015-02-14 14:41
  • 310

Handler造成Activity泄漏,用弱引用真的有用么?

网上很多教程,解决Handler造成的内存泄漏问题,基本上是使用弱引用来解决的,但是使用弱引用真的有效么?直接写代码演示,以及分析。 下面分析过程分为4种,第一种是Handler声明成静态的并且弱引用Activity。第二种是handler声明成成员变量的,使用弱引用。第三种是将handler声明成...
  • u013356254
  • u013356254
  • 2016-09-07 21:45
  • 5050
    个人资料
    • 访问:264669次
    • 积分:3005
    • 等级:
    • 排名:第13872名
    • 原创:46篇
    • 转载:0篇
    • 译文:0篇
    • 评论:329条
    QQ交流群

    Android路上

    611566797
    博客专栏
    我的公众号