Android内存管理之道

发布时间:2017-7-1 11:32:16编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Android内存管理之道 ",主要涉及到Android内存管理之道 方面的内容,对于Android内存管理之道 感兴趣的同学可以参考一下。

相信一步步走过来的Android从业者,每个人都会遇到OOM的情况。

怎样避免和防范OOM的出现。对于每个程序猿来说确实是一门不可缺少的能力。今天我们就谈谈在Android平台下内存的管理之道,開始今天的主题之前,先再次回想两个概念。


内存泄漏:对象在内存heap堆中中分配的空间。当不再使用或没有引用指向的情况下。仍不能被GC正常回收的情况。多数出如今不合理的编码情况下。比方在Activity中注冊了一个广播接收器。可是在页面关闭的时候进行unRegister,就会出现内存溢出的现象。通常情况下,大量的内存泄漏会造成OOM。


OOM:即OutOfMemoery,顾名思义就是指内存溢出了。内存溢出是指APP向系统申请超过最大阀值的内存请求,系统不会再分配多余的空间,就会造成OOM error。

在我们Android平台下。多数情况是出如今图片不当处理载入的时候。


内存管理之道嘛。无非就是先理解并找出内存泄漏的原因,再基于这些反式去合理的编码。去防范进而避免内存开销过大的情形。学习怎样合理的管理内存。最好先了解内存分配的机制和原理。仅仅有深层次的理解了内部的原理。才干真正避免OOM的发生。可是本文就不介绍Jvm/Davilk内存分配的机制了,如有兴趣。请查看历史消息。曾经做过题为《JVM执行时数据区域分析》的分享。


Android APP的所能申请的最大内存大小是多少,有人说是16MB。有人又说是24MB。这样的事情,还是亲自用自己的手机測试下比較靠谱。測试方式也比較简单。Java中有个Runtime类。主要用作APP与执行环境交互,APP并不会为我们创建Runtime的实例。可是Java为我们提供了单例获取的方式Runtime.getRuntime()。通过maxMemory()方法获取系统可为APP分配的最大内存,totalMemory()获取APP当前所分配的内存heap空间大小。

我手上有两部手机,一部Oppo find7,执行Color OS,实測最大内存分配为192MB。一部天语v9,执行小米系统。实測最大内存分配为100MB。这下看出点眉目了吧。因为Android是开源系统,不同的手机厂商事实上是拥有改动这部分权限能力的,所以就造成了不同品牌和不同系统的手机,对于APP的内存支持也是不一样的,和IOS的恒久100MB是不同的。一般来说,手机内存的配置越高,厂商也会调大手机支持的内存最大阀值,尤其是如今旗舰机满天公布的情况下。

可是开发人员为了考虑开发出的APP的内存兼容性,无法保证APP执行在何种手机上,仅仅能从编码角度来优化内存了。

以下我们逐条来分析Android内存优化的关键点。

1、万恶的static

static是个好东西。声明赋值调用就是那么的简单方便。可是伴随而来的还有性能问题。

因为static声明变量的生命周期事实上是和APP的生命周期一样的,有点类似与Application。

假设大量的使用的话。就会占领内存空间不释放。积少成多也会造成内存的不断开销。直至挂掉。

static的合理使用一般用来修饰基本数据类型或者轻量级对象,尽量避免修复集合或者大对象,经常使用作修饰全局配置项、工具类方法、内部类。

2、无关引用

非常多情况下,我们需求用到传递引用,可是我们无法确保引用传递出去后是否能及时的回收。比方比較有代表性的Context泄漏。非常多情况下当Activity 结束掉后。因为仍被其它的对象指向导致一直迟迟不能回收,这就造成了内存泄漏。这时能够考虑第三条建议。

3、善用SoftReference/WeakReference/LruCache

Java、Android中有没有这样一种机制呢,当内存吃紧或者GC扫过的情况下。就能及时把一些内存占用给释放掉,从而分配给须要分配的地方。

答案是肯定的,java为我们提供了两个解决方式。假设对内存的开销比較关注的APP,能够考虑使用WeakReference,当GC回收扫过这块内存区域时就会回收;假设不是那么关注的话,能够使用SoftReference。它会在内存申请不足的情况下自己主动释放,相同也能解决OOM问题。

同一时候Android自3.0以后也推出了LruCache类,使用LRU算法就释放内存。一样的能解决OOM,假设兼容3.0一下的版本号。请导入v4包。关于第二条的无关引用的问题。我们传參能够考虑使用WeakReference包装一下。

4、慎重handler

在处理异步操作的时候。handler + thread是个不错的选择。可是相信在使用handler的时候,大家都会遇到警告的情形,这个就是lint为开发人员的提醒。handler执行于UI线程,不断处理来自MessageQueue的消息,假设handler还有消息须要处理可是Activity页面已经结束的情况下。Activity的引用事实上并不会被回收,这就造成了内存泄漏。

解决方式,一是在Activity的onDestroy方法中调用

handler.removeCallbacksAndMessages(null);取消全部的消息的处理。包含待处理的消息。二是声明handler的内部类为static。

5、Bitmap终极杀手

Bitmap的不当处理极可能造成OOM。绝大多数情况都是因这个原因出现的。Bitamp位图是Android中当之无愧的胖小子,所以在操作的时候当然是十分的小心了。因为Dalivk并不会主动的去回收。须要开发人员在Bitmap不被使用的时候recycle掉。使用的过程中。及时释放是很重要的。同一时候假设需求同意。也能够去BItmap进行一定的缩放,通过BitmapFactory.Options的inSampleSize属性进行控制。假设仅仅仅仅想获得Bitmap的属性,事实上并不须要依据BItmap的像素去分配内存,仅仅需在解析读取Bmp的时候使用BitmapFactory.Options的inJustDecodeBounds属性。最后建议大家在载入网络图片的时候,使用软引用或者弱引用并进行本地缓存。推荐使用android-universal-imageloader或者xUtils。牛人出品,必属精品。前几天在讲《自己定义控件(三)  继承控件》的时候,也整理一个。大家能够去Github下载看看。

6、Cursor及时关闭

在查询SQLite数据库时,会返回一个Cursor,当查询完成后。及时关闭,这样就能够把查询的结果集及时给回收掉。

7、页面背景和图片载入

在布局和代码中设置背景和图片的时候。假设是纯色,尽量使用color;假设是规则图形,尽量使用shape绘图;假设略微复杂点,能够使用9patch图;假设不能使用9patch的情况下。针对几种主流分辨率的机型进行切图。

8、ListView和GridView的item缓存

对于移动设备,尤其硬件參差不齐的android生态,页面的绘制事实上是非常耗时的,findViewById也是蛮慢的。

所以不重用View,在有列表的时候就尤为显著了,常常会出现滑动非常卡的现象。详细參照历史文章《说说ViewHolder的还有一种写法》

9、BroadCastReceiver、Service

绑定广播和服务,一定要记得在不须要的时候给解绑。

10、I/O流

I/O流操作完成。读写结束,记得关闭。

11、线程

线程不再须要继续运行的时候要记得及时关闭。开启线程数量不易过多,一般和自己机器内核数一样最好,推荐开启线程的时候。使用线程池。

12、String/StringBuffer

当有较多的字符创须要拼接的时候,推荐使用StringBuffer。


今天没有代码。纯文字,纯手打,蛮辛苦。整理了这么多优化的策略。相信大家在理解后使用。再也不会遇上OOM了。


假设认为对你有所帮助。欢迎大家订阅我的微信公众账号——Android干货分享。以下是微信的二维码,为你提供及时高质的Android干货。

技术交流QQ群:318588906,欢迎大家加群,共同探讨下Android和Java技术,一起壮大我们的微信干货分享社区。



上一篇:Unity 网格 绘制
下一篇:理解Docker(4):Docker 容器使用 cgroups 限制资源使用

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款