Android中的性能优化是一个非常重要的内容,本文是自己在Android性能优化方面的学习笔记,主要总结了网上目前已经有的博客介绍的相关优化方法,同时结合自己的理解补充了一些。
一、概述
二、常用方法
1.布局优化
2.内存优化
3.其它优化
三、内存泄漏
四、相关工具
五、参考
一、概述
Android设备作为一种移动设备,不管是内存还是CPU都受到了一定的限制,无法做到像PC设备那样具有超大的内存和高性能的CPU,为了提高应用程序的性能,我们必须掌握常见的性能优化方法。
二、常用方法
总的来说,常见的性能优化方法主要如下:
布局优化
Android开发中一个很重要的部分就是布局的设计,一个好的交互界面必定会带来更好的用户体验,但是越复杂的界面往往越容易引起性能问题,我们需要做好布局优化。
- 1.合理选用布局
Android中系统对View的测量、布局和绘制时,都是通过对View树的遍历来进行操作的,布局优化的思想主要是尽量减少布局文件的层级。我们在选择使用布局时,也要尽量合理地选用布局,比如使用RelativeLayout相对布局来避免LinearLayout的过度嵌套。
- 2.避免过度绘制
过度绘制(Overdraw)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构里面,如果不可见的 UI 也在做绘制的操作,会导致某些像素区域被绘制了多次,同时也会浪费大量的 CPU 以及 GPU 资源。
通常过度绘制的解决办法有:
1)考虑去掉多余的背景
2)使用<include>、<merge>、ViewStub
include可以重用布局
merge一般和include一起使用减少布局的层级
ViewStub可以按需加载所需的布局文件 更多详细介绍
内存优化
- Bitmap优化
图片处理有关的Bitmap很占内存,在加载Bitmap时要尽量压缩,还要注意及时使用recycle()回收内存。
- 线程池的使用
线程池可以重用内部的线程,避免线程的创建和销毁带来的性能开销。
- 绘制优化
View的onDraw()方法要避免大量的操作,首先是onDraw()中不要创建新的局部对象,因为onDraw()方法可能会被频繁调用,这样会短时间内产生大量临时对象,降低程序执行效率,另外,onDraw()方法中不要做耗时任务。
- ListView优化
在使用ListView控件的时候,需要考虑进行优化,首先是复用convertView,其次是利用静态内部类ViewHolder来避免findViewById每次都进行查找从而达到优化。当然,我们也可以直接使用谷歌最新推出的控件RecyclerView来替代ListView。
- 缓存
使用内存缓存或者磁盘缓存。
其它优化
- 避免ANR
开启新的线程执行耗时操作。但是,频繁地创建和销毁线程可能会带来较大的性能开销,这时可以考虑使用线程池技术来重用线程,以达到优化的目的。
ANR(Application Not responding)。主线程(UI线程)如果在规定时内没有处理完相应工作,就会出现ANR。具体来说,ANR会在以下几种情况中出现:
- Activity输入事件(按键和触摸事件)5s内没被处理
- BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s)
- service 前台20s 后台200s未完成启动
- ContentProvider的publish在10s内没进行完
性能优化是个比较大的范畴,更多优化方法还是需要我们在实践中多多探索。
三、内存泄漏
内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。简单来说,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致GC不能回收。
Android中内存泄漏可能主要有4个方面:
- 1. 对象被生命周期长的对象引用不能释放
这种情况比较典型,例如某个类的静态变量引用了一个Activity,因为static静态变量的生命周期与应用的生命周期相同,那么将导致Activity无法释放。使用单例模式时如果不注意的话也会引起内存泄漏,需要注意。
- 2. 构造Adapter时,没有使用 convertView 重用
在ListView或者GridView的使用时,构建Adapter时,如果不使用 convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。
- 3. Bitmap对象不在使用时调用recycle()释放内存
Android中Bitmap对象往往比较占内存,当不再被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存。
- 4. 查询数据库后没有关闭游标cursor 。
资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。因为有些资源性对象,比如 SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null.在我们的程序退出时一定要确保我们的资源性对象已经关闭。
上面简单地列出了Android中内存泄漏的常见几种情况,下面是一篇最近看到的有关Java和Android中内存泄漏的文章,写的比较好。Java & Android 内存泄漏相关文章