性能优化的套路
1 减少过渡绘制
1.1 怎么查看是否存在过度绘制?
我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况。
蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域
1.2 怎么解决过度绘制?
1.2.1 移除Window默认的Background
在onCreate方法中加入,getWindow().setBackgroundDrawable(null);
1.2.2 移除XML布局文件中非必需的Background
1.2.3 自定义 View 时重写 hasOverlappingRendering 方法返回false。
该方法用来标记当前view是否存在过度绘制,存在返回ture,不存在返回false,默认返回为true。
当继承了hasOverlappingRendering()方法返回false后,android会自动进行合理的优化,避免使用offscreen buffer。
2 布局优化
2.1 减少布局的嵌套层级
可以hierarchyviewer去看布局的嵌套层级
原则:
1,用RelativeLayout减少嵌套的层级。
2,同等层级情况下可以实现的选用LinearLayout而不是RelativeLayout。
2.2 当某些UI满足某种条件才显示复杂UI就用ViewStub
在开发过程中,经常会遇到这样一种情况,有些布局很复杂但是却很少使用。例如条目详情、进度条标识或者未读消息等,这些情况如果在一开始初始化,虽然设置可见性 View.GONE ,但是在Inflate的时候View仍然会被Inflate,仍然会创建对象,由于这些布局又想到复杂,所以会很消耗系统资源。
ViewStub就是为了解决上面问题的,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。
2.3 有些大像素有规律的图片用.9去代替
2.4 去掉无用的UI
2.5 合并布局,用TextView代替图片加文字
3 分析代码耗时情况
可以通过traceview去分析代码的耗时情况。
traceView虽然很牛逼。但是网上大部分文章都是浅浅说一下。
经过这段时间不段试错,整理一个可行的套路。
套路开始:
3.1 生成.trace 文件
首先肯定生成用TraceView生成.trace文件。
生成.trace文件是方式有两种。
3.1.1 在DDMS工具中生成
最常用的使用方式
1,选择到DDMS界面,选择要检测耗时的进程,比如我的就是com.android.dialer
image.png2,点击采集如下图
image.png会出现这样的对话框(这个就是多长时间采集一次数据),点击ok即可。
image.png这时候开启采集按钮会编程停止采集的按钮(带黑色正方形)
image.png3,在手机执行你检测耗时的操作。比如:我想测试最近通话和联系人Tab的切换耗时。就去手动去不断去切换Tab界面或者也可以用脚本
4,执行完操作后,点击停止采集的按钮(带黑色正方形)停止采集,就会生成.trace文件,如下图:
3.1.2 在代码中用代码设置开始采集的点和停止采集的点
比如应用的冷启动,进程还没有出现是无法选择进程的。比如界面跳转的耗时情况想精确到哪里开启采集,哪里结束采集。就需要在代码中用代码设置。
下面以冷启动举个栗子
1,设置开始采集点--Debug.startMethodTracing();
在Application的onCreate()方法中写上Debug.startMethodTracing();为开始采集
2,设置结束采集点 -- Debug.stopMethodTracing();
我们就在主界面显示的时候设置采集结束点,可以在onResume的末尾,也可以在onWindowFocusChanged参数出入为true的时候设置结束点。
3,运行代码,生成.trace文件
那么.trace文件在哪里呢?
只可能在两个地方。
一就是在SD根目录
二就是在/sdcard/Android/data/包名/files/dmtrace.trace
4.取出来。相信大家都会。
注意:不采集了要把Debug.startMethodTracing();和Debug.stopMethodTracing();删掉。
3.2 打开.trace 文件
打开.trace文件也有两种方式:
3.2.1 在Eclipse上打开(建议你忘记这种方式)
为什么要忘记这种方式?
因为这个搜索用不了。
如果搜索用不了,那么3.3的快速找到耗时的方法就就进行不了。但是还是能找到耗时的方法的。但是就是体力活,说得更准确一点就是眼力活,我保证看到你想哭。所以忘记这样方式吧。
3,.2.2 用命令打开(推荐)
1,怎么用命令打开?
把.trace 文件拷贝到\sdk\tools这个文件夹下。
1.trace(因为我改名字了而已)。
在这文件夹打开命令行输入 traceview.bat 1.trace (.trace的全名称),如下图
就打开了,如下图
image.png用命令打开有什么好处呢?当然就是能搜索关键字啊!如下图
image.png但是在DDMS工具中生成.trace 文件默认就是在Eclipse上打开的。怎么办?
但是是找到这个DDMS生成的.trace 文件啊,但是在哪里呢?
鼠标放在这块区域,
看到没有,在这路径下。
image.png就在这里了。最好点击修改日期排序,第一个就你要找的文件了。
image.png3.3 快速找到耗时的方法
打开了,最重要的一步来了。这段时间的试错主要是在哪里试错,怎么快速找到耗时方法,而不是有了traceView还得用眼睛一行行去看,这是要累死人的节奏啊。
image.png圈中的从左到右
Name :该线程运行过程中所调用的函数名
Incl Cpu Time %: 某函数占用的CPU时间,包含内部调用其它函数的CPU时间的百分比
Incl Real Time : 某函数运行的真实时间(以毫秒为单位),内含调用其它函数所占用的真实时间
Call+Recur Calls/Total:某函数被调用次数以及递归调用占总调用次数的百分比
Real Time/Call: 同CPU Time/Call类似,只不过统计单位换成了真实时间
这上面是五个列是最重要的。其他列没有什么作用,为了不受影响,我们把这个五个列放到一起。
image.png这样就可以排除干扰列了,同时又有更大的空间看清楚Name列的函数名。
然后呢?
还记得Incl Real Time这列吗?这列就是函数的耗时时间。
我们就让这列的耗时时间从大到小排列。
点一下列名,就看到
函数的耗时时间从大到小排列了。
这样有什么用?
这时候就用到搜索功能了。
举个栗子
我就搜索com.andr(因为我的包名是com.android.dialer但是每一个类的命名都是以com.android.diaer开头的,所以我搜索了com.andr尽量搜索多一下结果,再判断是不是我程序的类)。
输入com.andr,一个个回车,直到找到自己的类的
image.pngonPageScrolled这方法总耗时436ms,调用一次耗时1.857ms。
他的函数里面方法
getRtlPosition(position);总耗时175.106ms,占了百分之45.5
再看代码。
这是viewpager的回调方法onPageScrolled,在切换的viewpager的时候会回调很多次。真的有必要在哪里判断是不是从右到左的语言吗?
所以改成:只要在onPageSelected的方法判断就行了。这个方法在切换完成后只回调一次。
改完之后,运行代码。再traceView一下。对比是否改好了。
用命令打开,优化的.trace 文件。
搜索onPageScrolled这个优化后的代码看总耗时和每次耗时多少。
很明显看出来上面的没有优化前的被调用235次一共耗时436.367ms。每次调用1.857ms
和优化后的被调用了319次才一共耗时279.367ms要小得多。每次调用1.721ms
接下就在原来的trace文件找耗时方法了。同上。
总结 : 就是根据Incl Real Time进行从耗时时间从长到短排序,然后搜索关键字符串,找属于自己的代码的耗时方法,优化即可
注意:traceView写的多少ms都不等同于代码的执行的真实时间。但是是代码执行真实时间的倍数。有可能是2倍,5倍,10倍什么的,但是一定具备参考意义。
关于这个套路和TraceView具体使用http://www.jianshu.com/p/2ef139f5dfac