本篇简单的讲一下平常使用Handler时造成内存泄漏的问题。

  什么是内存泄漏?大白话讲就是分配出去的内存,回收不回来。严重会导致内存不足OOM。下面来看一下造成内存泄漏的代码:

public class MemoryLeakActivity extends Activity {

    private MyHandler mHandler;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler); mHandler = new MyHandler();
mHandler.sendEmptyMessage(1);
} private class MyHandler extends Handler{ public MyHandler(){
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
}

上面的代码我们不用管发送消息、接受消息,因为之前已经详细讲过了,不是本篇的重点。本篇我想说上面的代码会造成内存泄漏,什么意思?Handler持有MemoryLeakActivity引用,为什么?如果不持有当前类的引用,我怎么更改当前类的ui或其他逻辑???或者我们知道内部类持有外部类引用也行。那么怎么解决那?

  解决办法:将内部类改为静态内部类,因为静态内部类不持有外部类引用。由于Handler不再持有外部类引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你还需要在Handler中增加一个对Activity的弱引用(使用弱引用的好处在于:activity一旦被置为null,他就会被立刻回收)。上面持有的引用属于强引用,强引用的特点就是当当前类被回收的时候,如果它被强引用所持有,那么当前类是不会被回收的!!!所以我们改成软引用持有当前类对象,这样在GC回收时会忽略掉弱引用,即就算有弱引用指向某对象,该对象也会在被GC检查到时回收掉。

public class MemoryLeakActivity extends Activity {

    private MyHandler myHandler;

    private static final int ACTION_GOTO_MAIN = 1001;
private static final int GOTO_MAIN_TIMER = 2 * 1000; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
myHandler = new MyHandler(this);
} @Override
protected void onResume() {
super.onResume();
if (myHandler != null) {
myHandler.sendEmptyMessageDelayed(ACTION_GOTO_MAIN, GOTO_MAIN_TIMER);
} } @Override
protected void onPause() {
super.onPause();
if (myHandler != null && myHandler.hasMessages(ACTION_GOTO_MAIN)) {
myHandler.removeMessages(ACTION_GOTO_MAIN);
} } protected static class MyHandler extends Handler {
private WeakReference<MemoryLeakActivity> mActivity; public MyHandler(MemoryLeakActivity activity) {
mActivity = new WeakReference<MemoryLeakActivity>(activity);
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MemoryLeakActivity activity = mActivity.get();
if (activity == null)
return;
if (msg.what == ACTION_GOTO_MAIN) {
//处理逻辑
}
}
}
}

上面代码很好的解决了内存泄漏的问题。但是这段代码可能会在很多界面都会遇到,难道每个界面都需要这样写吗?重复的工作啊,所以干脆我们抽取成一个基类,将来创建Handler的时候继承这个基类就好。

public abstract class WeakHandler<T> extends Handler {

    protected WeakReference<T> reference;

    //创建子线程Handler使用的构造器
public WeakHandler(Looper looper, T reference) {
super(looper);
this.reference = new WeakReference<>(reference);
} //创建主线程Handler使用的构造器
public WeakHandler(T reference) {
this.reference = new WeakReference<>(reference);
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
T t = reference.get();
if (t == null)
return;
handleMessage(t, msg);
} protected abstract void handleMessage(T t, Message message); }

上述代码,我们使用了泛型,这个泛型就是我们之前说的当前类,同时提供了两种构造器,这样不管我们是创建主线程还是非主线程Handler对象时,都不会造成内存泄漏了。

  至此,Handelr系列讲解到此结束,大多数都是参数慕课网的《Android面试常客Handler详解》,我这里只是将视频中的内容加上自己的理解纪录下来,希望对大家有所帮助。

Handler系列之内存泄漏的更多相关文章

  1. ios开发系列之内存泄漏分析(下)

    接上篇,本篇主要讲解通知和 KVO 不移除观察者.block 循环引用 .NSThread 和 RunLoop一起使用造成的内存泄漏. 1.通知造成的内存泄漏 1.1.ios9 以后,一般的通知,都不 ...

  2. ios开发系列之内存泄漏分析(上)

    ios自从引入ARC机制后,一般的内存管理就可以不用我们码农来负责了,但是一些操作如果不注意,还是会引起内存泄漏. 本文主要介绍一下内存泄漏的原理.常规的检测方法以及出现的常用场景和修改方法. 1.  ...

  3. 处理handler中的内存泄漏

    package de.bvb.test; import android.app.Activity; import android.os.Bundle; import android.os.Handle ...

  4. BaseHandler的封装, 处理handler中的内存泄漏

    package de.bvb.study.common; /** * 用于规范 Message.what此属性,避免出现魔法数字 */ public final class What { public ...

  5. Android实战技巧之三十八:Handler使用中可能引发的内存泄漏

    问题描写叙述 曾几何时,我们用原来的办法使用Handler时会有以下一段温馨的提示: This Handler class should be static or leaks might occur ...

  6. Android 内存泄漏总结

    内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收 ...

  7. Android开发之漫漫长途 番外篇——内存泄漏分析与解决

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. Android 内存泄漏总结(转)

    Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却 ...

  9. Java中关于内存泄漏出现的原因以及如何避免内存泄漏

    转账自:http://blog.csdn.net/wtt945482445/article/details/52483944 Java 内存分配策略 Java 程序运行时的内存分配策略有三种,分别是静 ...

随机推荐

  1. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  2. 虾扯蛋:Android View动画 Animation不完全解析

    本文结合一些周知的概念和源码片段,对View动画的工作原理进行挖掘和分析.以下不是对源码一丝不苟的分析过程,只是以搞清楚Animation的执行过程.如何被周期性调用为目标粗略分析下相关方法的执行细节 ...

  3. 06.SQLServer性能优化之---数据库级日记监控

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ...

  4. PHP-解析验证码类--学习笔记

    1.开始 在 网上看到使用PHP写的ValidateCode生成验证码码类,感觉不错,特拿来分析学习一下. 2.类图 3.验证码类部分代码 3.1  定义变量 //随机因子 private $char ...

  5. npm 使用小结

    本文内容基于 npm 4.0.5 概述 npm (node package manager),即 node 包管理器.这里的 node 包就是指各种 javascript 库. npm 是随同 Nod ...

  6. 如何用Java类配置Spring MVC(不通过web.xml和XML方式)

    DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servl ...

  7. 3种web会话管理的方式

    http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于我们的应用来说,我们是靠用户来管理,而不是靠客户端. ...

  8. iOS从零开始学习直播之2.采集

      直播的采集由采集的设备(摄像头.话筒)不同分为视频采集和音频采集,本篇文章会分别介绍. 1.采集步骤   1.创建捕捉会话(AVCaptureSession),iOS调用相机和话筒之前都需要创建捕 ...

  9. 在 Windows7 上按照 MySQL5.7

    在 Windows7 上按照 MySQL5.7 1.从官网下载最新版本的 MySQL,这里下载的是 mysql-5.7.17-win32: 2.将下载的 mysql-5.7.17-win32.zip ...

  10. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...