This Handler class should be static or leaks might occur(Handler优化之内存泄漏)

This Handler class should be static or leaks might occur(Handler优化之内存泄漏)

技术交流1群:46523908
技术交流2群:46505645
NoHttp 源码及Demo托管在Github欢迎大家Star:https://github.com/Y0LANDA/NoHttp

NoHttp是专门做Android网络请求与下载的框架,框架直播视频源码下载地址。

Handler之内存泄漏

  This Handler class should be static or leaks might occur (com.yolanda.nohttp6.activity.ThreadActivity.1)。这个警告写Android的人应该都遇到过,是在用new Handler时提示的:
This Handler class should be static or leaks might occur(Handler优化之内存泄漏)_第1张图片
  这个警告的意思是我们这么使用Handler会发生内存泄漏,有两个解决办法:
  1、如果确定我们的Handler在组件(Activity(Fragment)...)退出后不会收到异步发来的消息,我们这里用鼠标点击解决方案中的第一个或者第二个选项,开发工具会在Handler或者组件上添加注解,例如:

@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
    public void handleMessage(Message msg) {};
};

  这样注解之后那个警告就没了。
  2、但是这不能保证我们不发生内存泄漏问题,所以Yolanda这里给大家一种解决方案。我们先来做个分析,我们使用Handler发生内存泄漏无非是当我们Activity/Fragment或者其他组件销毁后,Handler从异步发来消息后更新UI,然后发生了内存泄漏,发生了异常,可能导致APP崩溃。所以我们想到在Handler中用弱引用来引用Activity/Fragment
  3、普及一下弱引用的常识,弱引用就是不保证不被垃圾回收器回收的对象,它拥有比较短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域过程中,一旦发现了只具有弱引用的对象,就会回收它的内存,不过一般情况下,垃圾回收器的线程优先级很低,也就不会很快发现那些只有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用的对象被垃圾回收的话,Java虚拟机就会把这个弱引用加入相关的引用队列中。简单些来说,当我们的Activity/Fragment销毁后这个对象不存在,即被垃圾回收期回收。随意我们用它来做下简单的封装:

重写Handler:

public class BaseHandler extends Handler {

    private WeakReference<BaseActivity> reference;

    public BaseHandler(BaseActivity activity) {
        reference = new WeakReference<BaseActivity >(activity);
    }

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

重写组件,提供handleMessage(Message)方法

  这里我们以Activity为例,我们看到上面Hanlder#handleMessage(Message)被触发后有一个判断if (reference != null && reference.get() != null)这里判断了弱引用对象是否为null,如果不为null就调用它的一个handleMessage(Message)方法,我们知道Activity必定是没有void handleMessage(Message msg);方法的,所以我们写一个抽象类,接下来带大家实现BaseActivity

public abstract class BaseActivity extends Activity {

    /** * 处理Handler的消息 * * @param msg */
    public abstract void handleMessage(Message msg);
}

  这样我们使用的时候Activity继承BaseActivity接口就可以了,然后重写handleMessage(Message msg);方法就可以了。

使用方法

  我们这里以Activity为例来写一个示范:

public class TestHandlerActivity extends BaseActivity {

    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mHandler = new BaseHandler(this);
        ...
    }

    @Override
    public void handleMessage(Message msg) {
    }

}

  这里只是用Activity举例,我们平常的Fragment和Dialog等都可以这么使用。

NoHttp 源码及Demo托管在Github欢迎大家Star:https://github.com/Y0LANDA/NoHttp

你可能感兴趣的:(优化,android,handler,内存泄露,NoHttp)