不管是web端的开发,还是移动端的开发,为了提高性能,对内存的优化都是必不可少的,android开发中内存优化也是非常重要的知识点,今天和大家分享的就是android内存优化的关键点,希望可以帮助大家更好地学习android。
1、优化布局文件
界面是 Android 应用中直接影响用户体验最关键的部分,不合理的XML布局会使界面容易发生卡顿且导致应用占用大量内存。一个界面要显示出来,第一步会进行解析布局,在 requestLayout 之后还要进行一系列的 measure 、 layout 、 draw 操作,若布局文件嵌套过深、拥有的标签属性过于臃肿,每一步的执行时间都会受到影响,而界面的显示是进行完这些操作后才会显示的,所以每一步操作的时间增长,最终显示的时间就会越长。写布局文件的时候请多检查和多思考,用最优的方式实现布局。下面建议Android端做的几点优化工作:
第一,尽量减少XML布局文件中视图层级。主要是自查所有的布局XML文件,去除XML文件中无用的分支和XML文件中无用的父控件。Android对于视图中控件的布局渲染等会消耗很多的资源和内存,布局越复杂就越容易出现性能问题,尽量避免不必要的嵌套。
第二,去掉Window的默认背景。当我们使用了Android自带的一些主题时,window会被默认添加一个纯色的背景,这个背景是被DecorView持有的。当我们的自定义布局时又添加了一张背景图或者设置背景色,那么DecorView的background此时对我们来说是无用的,但是它会产生一次Overdraw,带来绘制性能损耗。我们可以自定义theme添加@null去除默认背景,所做修改示例如下所示:
2、排查静态变量使用是否合理
在优化过程中,需要对代码中的静态变量特别留意,静态变量是类相关的变量,它的生命周期是从这个类被声明,到这个类彻底被垃圾回收器回收才会被销毁。所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,直到程序退出。如果不注意,静态变量引用了占用大量内存的资源,造成垃圾回收器无法对内存进行回收,就可能造成内存的浪费。static一般用来修饰基本数据类型或者轻量级对象,常用作修饰全局配置项、工具类方法、内部类,尽量避免修复集合或者大对象。
3、修改Handler类为static类型,并且使用对外部类的弱引用
在处理异步操作的时候,handler + thread是个不错的选择。但是相信在使用handler的时候,大家都会遇到This Handler class should be static or leaks might occur警告的情形,意思是Handler类应该为static,否则可能造成内存泄露。当Activity被finish()掉,Message 将存在于消息队列中长达10分钟的时间才会被执行到,这个Message持有一个对Handler的引用,如果Handler是个非静态类,则也会持有一个对于外部类的隐式引用,这些引用在Message被执行前将一直保持,这样会保证Activity的上下文不被垃圾回收机制回收,同时也会泄露应用程序的资源(views and resources),为解决这个问题,将Handler改成静态内部类,并且使用对外部类的弱应用。静态匿名内部类不会持有一个对外部类的隐式引用,因此Activity将不会被泄露。如果你需要在Handler中调用外部Activity的方法,就让Handler持有一个对Activity的WeakReference,这样就不会泄露Activity的上下文了。所以当我们使用时要非静态内部类时要格外注意,如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露,倾向于建议使用静态类和弱引用的方法解决这种问题。
4、Bitmap要注意压缩和缓存,并且及时回收
Bitmap的不当处理极可能造成OOM,绝大多数情况都是因这个原因出现的。Bitamp位图是Android中当之无愧的最消耗内存的,所以在操作的时候当然是要十分地小心了。由于Dalivk并不会主动的去回收,需要开发者在Bitmap不被使用的时候recycle掉,使用的过程中,及时释放是非常重要的。同时如果需求允许,建议对Bitmap进行一定的压缩。最后建议大家在加载网络图片的时候,缓存通用的Bitmap对象。
5、及时关闭资源
Cursor是Android查询数据后得到的一个管理数据集合的类。正常情况下,如果我们没有关闭它,系统会在回收它时进行关闭,但是这样的效率特别低。如果查询得到的数据量较小时还好,如果Cursor的数据量非常大,就可能出现内存问题,所以一定要及时关闭Cursor。
同样地,文件读取操作需要使用缓存类,并且及时关闭文件。
6、避免创建不必要的对象
创建任何一个对象都需要消耗一定字节的内存开支,因此创建对象也是会一定程序上影响内存的,创建越多的对象,意味着分配的内存越多,虽然GC可以回收不用的对象,但是回收它们同样也需要耗费资源,所以建议一定不要创建不必要的对象。
7、对Adapter进行优化
对于移动设备,尤其硬件参差不齐的android生态,页面的绘制其实是很耗时的,findViewById也是蛮慢的。所以在项目中如果有类似ListView或GridView等控件时候,在adapter的getView()方法中一定要重用item缓存,很大程度上可以减少内存的消耗。
8、优化字符串处理,合理选择String、StringBuffer、StringBuilder
String、StringBuffer、StringBuilder都与字符串有关,但是其处理机制是不同的。String类是不可改变的量,也就是创建后就不能再修改了;StringBuffer、StringBuilder基本相同,都是可变字符序列,不同点是:StringBuffer是线程安全的,StringBuilder是线程不安全的。在性能方面,由于String类的操作都是产生新的String对象,而StringBuffer和StringBuilder只是一个字符数组的再扩容而已,所以String类的操作要远慢于StringBuffer和StringBuilder。在字符串不经常变化的场景中可以使用String类;在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程的环境中,则可以考虑使用StringBuffer;在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程的环境中,则可以考虑使用StringBuilder。
文章来源:公众号