Android代码优化之Handler内存泄漏
目录
前言
Android代码中涉及进程间通信的地方经常会使用Handler。
public class MainActivity extends AppCompatActivity { //可能引入内存泄漏的方法 private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
而上面这种用法可能会导致内存泄漏,比如使用如下代码,由于消息会在5分钟后发送,所以当用户进入并退出Activity后,在消息发送并处理完成之前,这个Activity是不会被回收的,这样就会导致内存泄漏。
public class MainActivity extends AppCompatActivity { //可能引入内存泄漏的方法 private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //5分钟后发送消息 handler.postDelayed(new Runnable() { @Override public void run() { Log.e("测试","123"); } },1000*10*5); } }
内存泄漏的原因
由于Handler、Looper和MessageQueue是一起工作的,在Android中一个应用启动后系统会默认创建一个用于处理主线程所有Message对象的Looper对象,它的生命周期贯穿于整个应用的生命周期,所以在主线程使用Handler的时候都会默认绑定这个Looper对象并关联MessageQueue,这时发送到MessageQueue的Message对象都会持有这个Handler对象的引用,这样Looper在处理消息的时候才能回调到Handler中年的handleMessage方法。因此如果Message对象还没有处理完成,那么Handler对象也就不会被垃圾回收。而在Java中非静态内部类会持有外部类的一个隐式引用,所以当Handler无法回收时由于Handler持有MainActivity的引用导致MainActivity也无法被回收,从而导致内存泄漏。
解决方法:将Handler改为静态内部类并使用弱引用
public class MainActivity extends AppCompatActivity { private final InnerHandler mInnerHandler=new InnerHandler(this); private final Runnable sRunnable=new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "解决方法", Toast.LENGTH_SHORT).show(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mInnerHandler.postDelayed(sRunnable,1000*60*5); } private static class InnerHandler extends Handler{ private final WeakReference<MainActivity> activityWeakReference; public InnerHandler(MainActivity activity) { this.activityWeakReference = new WeakReference<MainActivity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); MainActivity activity=activityWeakReference.get(); if(activity!=null){ } } } }
个人技术博客:https://myml666.github.io/
我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
视频点播 SDK-播放器问题
使用阿里云播放器 目前随便手机型号的增加,和大量短视频的接入,VOD 点播播放器会遇到各种奇葩问题,今天从几个非常多的案例入手讲下坑点。 案例分析:ios 3.4.7 播放器 crash 现象:客户 app 播放教学视频时初始化播放器后播放时直接 crash 。 分析: 出现问题,先看下视频编码,发现客户源文件是 vcodec 是 h264 ,acodec 是 amr ,可以使用 ffprobe 命令分析视频的编码。而点播播放器目前仅支持 MP3、AAC 两种 acodec。 结论: 已知的一个问题 3.4.7 的播放器在播放的音频不支持的情况下会出现 crash ,正常的情况应该是不支持播放会卡住而不是 crash ,此问题会随着新版本发布解决调。 案例分析:ios 3.4.7 切后台会从头重新播放 客户播放架构: 客户集成 3.4.7 的 dem
- 下一篇
原生Js交互之DSBridge
文章链接:https://mp.weixin.qq.com/s/Iqd0dKM-ZW4UwkIgSTnvYg 在上一篇文章「android 记一次富文本加载之路」中 介绍了关于android加载富文本的方法,其中提到的加载html 文件的,app拿到后台的json格式数据,传到html模板文件里进行渲染交互,如下的一段html代码 设函数<img src="http://equation.kaoyanvip.cn/?mml=%3Cmath%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1998%2FMath%2FMathML%22%3E%3Cmi%3Ef%3C%2Fmi%3E%3Cmfenced%3E%3Cmrow%3E%3Cmi%3Ex%3C%2Fmi%3E%3Cmo%3E%2C%3C%2Fmo%3E%3Cmi%3Ey%3C%2Fmi%3E%3C%2Fmrow%3E%3C%2Fmfenced%3E%3Cmo%3E%3D%3C%2Fmo%3E%3Cmfenced%20open%3D%22%7B%22%20close%3D%22%22%3E%3Cmt...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境