先看一组简单的代码

1
2
3
4
5
6
7
8
9

public class SampleActivity extends Activity {private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// ... }}
}

当我们这样写在一个Activity中时,Android Lint会提示我们这样一个 warning: In Android, Handler classes should be static or leaks might occur.
意思说:在Android中,Handler 类应该是静态的否则可能发生泄漏。

为什么会是这样呢?

了解一下Handler

  1. 当Android程序第一次创建的时候,在主线程同时会创建一个Looper对象。Looper实现了一个简单的消息队列,一个接着一个处理Message对象。程序框架所有主要的事件(例如:屏幕上的点击时间,Activity生命周期的方法等等)都包含在Message对象中,然后添加到Looper的消息队列中,一个一个处理。主线程的Looper存在整个应用程序的生命周期内。
  2. 当一个Handler对象在主线程中创建的时候,它会关联到Looper的 message queue 。Message添加到消息队列中的时候Message会持有当前Handler引用,当Looper处理到当前消息的时候,会调用Handler#handleMessage(Message).
  3. java中,no-static的内部类会 隐式的 持有当前类的一个引用。static的类则没有。

在什么地方引起了内存的泄露呢?再看看下面一段代码

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public class SampleActivity extends Activity {private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// ...}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 发送一个10分钟后执行的一个消息mHandler.postDelayed(new Runnable() {@Overridepublic void run() { }}, 600000);// 结束当前的Activityfinish();}
}

Activity结束后,在 Message queue 处理这个Message之前,它会持续存活着。这个Message持有Handler的引用,而Handler有持有Activity(SampleActivity)的引用,这个Activity所有的资源,在这个消息处理之前都不能也不会被回收,所以发生了内存泄露。

解决办法,看下面一段代码

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

public class SampleActivity extends Activity {/**
   * 使用静态的内部类,不会持有当前对象的引用
   */private static class MyHandler extends Handler {private final WeakReference<SampleActivity> mActivity;public MyHandler(SampleActivity activity) {mActivity = new WeakReference<SampleActivity>(activity);}@Overridepublic void handleMessage(Message msg) {SampleActivity activity = mActivity.get();if (activity != null) {// ...}}}private final MyHandler mHandler = new MyHandler(this);/**
   * 使用静态的内部类,不会持有当前对象的引用
   */private static final Runnable sRunnable = new Runnable() {@Overridepublic void run() { }};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//  发送一个10分钟后执行的一个消息mHandler.postDelayed(sRunnable, 600000);// 结束finish();}
}

ok,结束

NOTE: 好多人有担心弱引用的Activity回收的情况,这个完全不用担心的,因为我们在这个界面的时候,这个Activity 是不会被回收的,想想 如果我们的这个Activity被回收了,我们的这个界面是怎么存在的呢?

NOTE2: 各位,我是参照AsyncTask ,查看文档和自己的理解,存在我解释不了的地方,还望见谅,如有错误还望见谅。

NOTE3:具体怎么防止泄漏我也说不清楚,但是Handler 下面有一段源码

1
2
3
4
5
6

 final Class<? extends Handler> klass = getClass();if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&(klass.getModifiers() & Modifier.STATIC) == 0) {Log.w(TAG, "The following Handler class should be static or leaks might occur: " +klass.getCanonicalName());

转载于:https://www.cnblogs.com/zsw-1993/p/4879908.html

Handler 引起的内存泄露相关推荐

  1. 非静态内部类Handler类引起内存泄露

    最近在项目中使用延时Handler做Splish页面的跳转. new Handler().postDelayed(new Runnable() {@Overridepublic void run() ...

  2. android handler内存,Android handler之内存泄露原因揭示

    关于handler机制大家可以看前面专题Android面试精选--再聊android Handler机制.今天我们要说的重点是 handler为什么会发生内存泄露? 我们先从源头说起,应用刚启动时,第 ...

  3. Android Handler的内存泄露场景分析

    在前面一篇博客<Android全面解析Handler>一文中,我们认识了Handler的异步通信机制,同时也提到过Handler如果使用不慎将会导致内存泄露.今天主要来讲述一下Handle ...

  4. 彻底搞懂Java内存泄露

    Java内存回收方式 Java判断对象是否可以回收使用的而是可达性分析算法. 在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的.这个算法的基本思路就是通过一系列名为& ...

  5. Android之内存泄露、内存溢出、内存抖动分析

      内存 JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆.栈和方法区. 栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放.优点:速度快. 堆(heap) ...

  6. python 单例模式内存泄露_彻底搞懂Java内存泄露

    之前一直在简书写作,第一次发布到SF上来,也是第一次使用SF,后面会尽量同步到SF,更多文章请关注: 简书 编程之乐 转载请注明出处:谢谢! Java内存回收方式 Java判断对象是否可以回收使用的而 ...

  7. Android开发-Handler引起的内存泄漏-实验、分析、总结。

    介绍 最近在恶补Handler的知识,其中就涉及到了Handler引起的内存泄露问题,网络上有很多的分析文章.我就按照这些文章的思路,写代码验证,主要是验证和记录.  使用的内存检测工具是:LeakC ...

  8. 全方位带你彻底搞懂Android内存泄露

    1 Java内存回收方式 Java判断对象是否可以回收使用的而是可达性分析算法. 在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的.这个算法的基本思路就是通过一系列名 ...

  9. Android使用Handler造成内存泄露的分析及解决方法

    Android使用Handler造成内存泄露的分析及解决方法 参考文章: (1)Android使用Handler造成内存泄露的分析及解决方法 (2)https://www.cnblogs.com/xu ...

最新文章

  1. 个人银行账户管理程序
  2. python写入csv文件的几种方法
  3. ELK出现unassigned_shards查看及删除
  4. 用户输入与while循环
  5. Bash脚本教程之启动环境
  6. 计算机网络 --- 数据链路层CSMA/CD协议
  7. java方法的传递方式_JAVA基础--方法传参
  8. 4月编程语言排行榜:C++ 重回前三,PHP 呈下降势头
  9. ●BZOJ 4453 cys就是要拿英魂!
  10. 【BZOJ】1579: [Usaco2009 Feb]Revamping Trails 道路升级
  11. linux磁盘配额测试,linux磁盘配额练习题
  12. bootstrap切换tab页局部刷新_bootstrap在 刷新页面,tab选择页面不会改变。
  13. 前端 angular 和 bootstrap 的安装步骤
  14. 中级软件测试技能,中级软件测试工程师的职责描述精选
  15. Web Uploader文件(图片)上传使用方法
  16. RocketMQ 延迟队列
  17. Tecplot —— 探针提取数据集任一点数值
  18. lol s7 linux,LOLs7 赛季季末冲刺挑战赛参加地址介绍
  19. Java 数据持久化系列之JDBC
  20. 关于python中Graphviz画图时报错的解决方法

热门文章

  1. 检验mysql安装成功win7,手把手教你win7系统成功安装 RMySQL的处理对策
  2. dqn系列梳理_讲人话系列——DQN初探之2048
  3. php 完整redis类,PHP Redis类
  4. matlab在循环中保存jpg格式_Matlab如何循环读取文件
  5. python小人画爱心_使用Python画出小人发射爱心的代码
  6. mysql查询php输出表格_MySql数据库查询结果用表格输出PHP代码示例_PHP教程
  7. Android编程中利用AudioTrack播放PCM数据在音频的最后出现重复回声现象的解决方案
  8. pip 安装 rdkit
  9. Altium AD20如何选择重叠在下方的元件?如何对元件快速选择、选择区域内部、选择矩形接触到的对象
  10. DW06、DW07 锂电保护IC手册电路,锂电池过充过放过流短路保护芯片电路