作为大部分的Android开发来说,很多时候都在拉界面,写业务,做优化。
在写我们的界面和业务的时候,UI的优化便会显得至关重要。因为当你的UI代码写得很垃圾的时候,就会造成卡顿,丢帧等现象(造成卡顿的原因很多,UI只是其中一中)。
Android 应用的卡顿、丢帧等,这些影响用户体验的因素绝大部分都与16ms这个值有关。Android 设备的刷新率也是 60Hz,Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果超过了16ms,我们则认为发生了卡顿。
而Android端显示原理用一句话描述就是:Android应用程序调用SurfaceFlinger服务把经过测量、布局和绘制后的Surface渲染到显示屏幕上。
在我们的实际开发中,布局代码很多时候是通过xml和一些自定义控件来实现的。
那么在我们写布局代码XML的时候,我们可以对一些方向进行优化
- 避免过度绘制,减少布局层级;
- 有些时候,一个界面控件过多,如果只用线性布局和相对布局,会嵌套很多层级来实现绘制,这样绘制层级过高,可以用相对布局来约束各个控件的位置,减少层级。如果是简单的布局是否可以直接使用FrameLayout、LinearLayout来实现等等。
- 去掉无用的背景,资源;
- 过度绘制就是在绘制界面时,对同一个像素重复绘制了多次,但是用户能够看到的也只有最顶层绘制的内容,所以,是否可以去掉无用的背景,图片是否可以不要预设的图片资源,textview的文案是否可以先不设置。去除无用的父节点,子节点
避免View重叠;
使用?
canvas.clipRect()方法实现
只截取可见的部分,这样就能避免View重叠导致的过度绘制的问题 ,例如显示一把扑克牌的时候,因为只需要展示左边的数字就行了,所以使用此方法,不可见的部分就不会去绘制。- 使用合适的控件;
- 在项目中,可以根据项目场景使用合适的控件,例如
- ViewStub是一个可用于性能优化的控件,它是一个不可见的、零尺寸的View,可以在运行时进行延迟加载一个布局文件,从而提高显示速率。
viewstub和include比较像,都是在一个布局文件中嵌入另外一个布局文件,然而viewstub可以延迟加载,它只会在手动指定加载的时候才会加载这个布局文件,而include则会立即加载。
因此,不是必须显示的布局就可以使用ViewStub来代替,这样可以减少界面首次加载时资源消耗,提升最初加载速度。比如在无数据或者网络错误的时候,需要单独显示一个布局,那么这个布局就可以用ViewStub。、
使用merge;通过merge可以消除视图层次结构的冗余;merge标签必须使用在根布局;tips:对merge标签设置的属性是无效的。
使用一些异步加载框架;
避免View重叠实现代码;
// 老办法
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDroids.length > 0 && mDroids.size() == mDroids.length) {
for (int i = 0; i < mDroidCards.size(); i++) {
// 每一张卡牌平移的位置
mCardLeft = i * mCardSpacing;
// 绘制整张卡牌
drawDroidCard(canvas, mDroidCards.get(i), mCardLeft, 0);
}
}
}
// 优化后
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDroids.length > 0 && mDroids.size() == mDroids.length) {
int i;
for (int i = 0; i < mDroidCards.size() - 1; i++) {
mCardLeft = i * mCardSpacing;
canvas.save();
// 只绘制截取卡牌可见部分
canvas.clipRect(mCardLeft,
0,
mCardLeft + mCardSpacing,
mDroidCards.get(i).getHeight());
drawDroidCard(canvas, mDroidCards.get(i), mCardLeft, 0);
canvas.restore();
}
// 绘制最后一张完全可见的卡牌
drawDroidCard(canvas, mDroidCards.get(mDroidCards.size() - 1),
mCardLeft + mCardSpacing, 0);
}
}
如何查看是否过度绘制?
? ? ? ? 自定义View在开发中十分常见,当需要实现一个较为复杂的view时,就很容易漏掉很多细节。
常见问题: