Android 过度绘制问题
过度绘制(Overdraw)
过度绘制会引起界面卡顿
如何检测过度绘制
Android手机上面的开发者选项提供了工具来检测过度绘制,可以按如下步骤来打开:
开发者选项->调试GPU过度绘制->显示过度绘制区域
多次绘制的显示效果
绘制优化方案
- 去除不必要的背景
1.在theme中设置
<style name="AppTheme" parent="主题">
<item name="android:windowBackground">@null</item>
</style>
2.在Activity的onCreate()方法中添加:
getWindow().setBackgroundDrawable(null);
-
使用Inspector 在AS中查看 Layout 层级
这里使用Android推荐的Layout Inspector来查看layout的层次结构。 在Android Studio中点击Tools > Android > Layout Inspector。然后在出现的 Choose Process 对话框中,选择想要检查的应用进程即可。
使用 merge 标签在使用时 将相同布局嵌套的时候【去重】
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
...
/>
<TextView
...
/>
</merge>
多使用扁平化布局
可以使用更扁平化的布局,如RelativeLayout、GridLayout、ConstraintLayout等布局来提高性能。布局默认的最大深度为10。
比如:在TextView上设置带透明度alpha值的黑色文本可以实现灰色
的效果。但是,直接通过设置灰色的话能够获得更好的性能。
尽量少使用透明度
使用了透明度的View 会进行两次绘制,1 要先知道下一层的View是什么,2 在结合上一层的 View 进行混合处理
减少onDrwa 绘制层数 使用canvas clipRect()
一般
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < imgs.length; i++) {
canvas.drawBitmap(imgs[i], i * 100, 0, mPaint);
}
}
使用 clipRect()
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < imgs.length; i++) {
canvas.save();
if (i < imgs.length - 1) {
//前面的n-1张图,只裁剪一部分
canvas.clipRect(i * 100, 0, (i + 1) * 100, imgs[i].getHeight());
} else if (i == imgs.length - 1) {
//最后一张,完整的
canvas.clipRect(i * 100, 0, i * 100 + imgs[i].getWidth(), imgs[i].getHeight());
}
canvas.drawBitmap(imgs[i], i * 100, 0, mPaint);
canvas.restore();
}
使用ViewStub 标签延迟加载(在需要时才显示该UI)
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
这里的panel_import就是具体要加载的布局ID。
通过以下代码即可在需要时加载布局:
findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
或者
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
onDraw()的使用
-
onDraw()中不要创建新的局部变量以及不要做耗时操作
-
onDraw()中不要创建新的局部变量,因为onDraw()方法可能会被频繁调用,大量的临时对象会导致内存抖动,会造成频繁的GC,从而使UI线程被频繁阻塞,导致画面卡顿。
使用ConstraintLayout
ConstraintLayout相比RelativeLayout,其性能更好,也更容易使用,结合Android Studio的布局编辑器可以实现拖拽控件来编写布局等等。