【学习笔记】Android性能优化----->布局优化

本秂侑毒 提交于 2019-11-27 13:46:25

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");



不管使用哪种方式,一旦<ViewStub>被设置为可见或是inflate了,<ViewStub>就不存在,取而代之的是被inflate的Layout,

并将这个Layout的ID重新设置为<ViewStub>中通过android:inflatedId属性所指定的ID,

这也是为什么两次调用inflate方法会报错的原因。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!