1.AndroidUI渲染机制
人眼所感觉的流畅画面,需要画面的帧数达到40帧每秒到60帧每秒
在Android中,系统通过VSYNC信号触发对UI的渲染/重绘,其间隔时间是16ms,这个16ms其实就是1000ms中
显示60帧画面的单位时间,即1000/60
如果系统每次渲染的时间都保持在16ms之内,那我们看见的UI界面将是非常流畅的
但这也就需要将所有程序的逻辑都保证在16ms之内
如果不能在16ms内完成绘制,那么就会造成丢帧现象,即当前该重绘的帧被未完成的逻辑阻塞
例如一次绘制任务耗时20ms,那么在16ms系统发出VSYNC信号时就无法绘制,该帧就被丢弃,等待下次信号才开始绘制,
导致16*2ms内都显示同一帧画面,这就是画面卡顿的原因
Android系统提供了检测UI渲染时间的工具,打开“开发者选项”,选择“Profile GPU Rendering”,
并选中“On screen as bars”的选项,这时候在屏幕上将显示一些条形图。
每一条柱状线包含三部分:蓝色代表测量绘制Display List的时间,红色代表OpenGL渲染Display List所需要的时间,
黄色代表CPU等待GPU处理的时间。
中间的绿色横线代表VSYNC时间16ms,需要尽量将所有条形图都控制在这条绿色之下。
2.避免Overdraw
Overdraw,过度绘制会浪费很多的CPU/GPU资源
例如系统默认会绘制Activity的背景
而如果再给布局绘制了重叠的背景,那么默认Activity的背景就属于无效的过度绘制-Overdraw.
Android系统在开发者选项中提供了这样一个检测工具-"Enable GPU Overdraw".激活后,可以通过界面上的颜色来判断Overdraw的次数。
尽量增大蓝色区域,减少红色区域。
3.优化布局层级
在Android中,系统对View进行测量/布局和绘制时,都是通过对View数的遍历来进行操作的。
如果一个View树的高度太高,就会严重影响测量/布局和绘制的速度,因此优化布局的第一个方法就是降低View树的高度。
Google在其API文档中建议View树的高度不宜超过10层。
在早期的Android版本中,Google使用LinearLayout作为默认创建的XML文件的根布局。
而现在的版本的Android中,Google已经使用RelativeLayout来替代LinearLayout作为默认的根布局。
其原因就是通过扁平的RelativeLayout来降低通过LinearLayout嵌套所产生布局树的高度,从而提高UI渲染的效率。
实际使用时,如果布局中既可以使用LinearLayout也可以使用RelativeLayout,那么就采用LinearLayout,因为RelativeLayout布局过程需要花费更多的CPU时间。
如果需要通过嵌套的方式来完成布局,这种情况下还是建议采用RelativeLayout。
因为ViewGroup的嵌套就相当于增加了布局的层级,会降低程序的性能。
4.避免嵌套过多无用布局
嵌套的布局会让View树的高度变得越来越高,
选择不同的Layout组件,从而避免通过某一种Layout组件来实现功能的局限性,从而造成嵌套过多的情况发生。
4.1.使用<include>标签重用Layout
4.2.使用<ViewStub>实现View的延迟加载
<ViewStub>也可以引用并实现延迟加载。
<ViewStub>是一个非常轻量级的组建,它不仅不可视,而且大小为0.
可以通过setVisibility()方法来显示
可以通过ViewStub的inflate()方法来显示这个View
通过inflate()方法可以返回引用的布局,从而可以再通过View.findViewById()方法来找到对应的控件。
代码:
ViewStub mViewStub = (ViewStub)findViewById(R.id.mViewStub);
// mViewStub.setVisibility(View.VISIBLE);
View view = mViewStub.inflate();
TextView tv_stub = (TextView)findViewById(R.id.tv_stub);
tv_stub.setText("ViewStub");
并将这个Layout的ID重新设置为<ViewStub>中通过android:inflatedId属性所指定的ID,
这也是为什么两次调用inflate方法会报错的原因。
来源:oschina
链接:https://my.oschina.net/u/218078/blog/617292