Android知识笔记之性能优化:过渡绘制解决方案,我拿到了梦寐以求的字节跳动和腾讯双offer

**方法二:通过adb命令开启GPU过渡绘制调试 **

当然,如果每次都进入系统设置嫌麻烦,可以使用adb命令进行开启和关闭:

开启『调试 GPU 过度绘制』:

adb shell setprop debug.hwui.overdraw show

关闭『调试 GPU 过度绘制』:

adb shell setprop debug.hwui.overdraw false

执行命令之后可能需要重新启动你当前开发的应用。

颜色与过渡绘制:

  • 原色:没有过度绘制

  • 蓝色:1 次过度绘制

  • 绿色:2 次过度绘制

  • 粉色:3 次过度绘制

  • 红色:4 次及以上过度绘制

在平时的开发中,如果出现粉色及以上的过渡绘制情况。说明过渡绘制以及很严重了。需要进行优化。

3. 优化过渡绘制

1. 去除Activity自带的默认背景颜色:

查看Android源码里的Theme主题,如下:

也就是说继承Theme这个style的风格,默认情况下,新建一个Activity都是有背景的。正常情况下,很多界面其实是不需要背景的。

下面是华为自带天气APP的首页,我们可以看到文字部分以及图标部分都是绿色,说面已经是第三层过渡绘制了,其中背后天气图是一层,文字又是一层,正常来说应该只有两层,也就是文字和图标应该是蓝色。

那么这多出来的一层应该就是Activity自带的背景色了。也就是theme里面设置的。

我们只要在自己的AppTheme里面去除该背景色即可:

或者在Activity的onCreate方法中:

getWindow().setBackgroundDrawable(null);

2. 使用Canvas的clipRect和clipPath方法限制View的绘制区域

一个Activity对应有一个Canvas,也就是画布,画布的概念就是一个画板,这个画布提供了很多的API,我们可以通过调用画布的API来绘图以及对画布做一些操作,clipRect方法用来裁切画布上的一个矩形区域,该矩形区域用Rect对象来描述。调用了clipRect之后,画布的可绘制区域减小到和Rect指定的矩形区域一样大小。所有的绘制将限制在该矩形范围之内。这里的裁切概念和PS里的裁切类似。

典型的例子,抽屉布局,找了网易云音乐开刀:

注意观察左侧抽屉打开的时候,抽屉布局和背后布局重叠在一起了,此时整个屏幕一多半都变成了红色,过渡绘制严重。

在抽屉布局弹出时,抽屉布局是不透明的,也就是说抽屉布局背后挡住的内容布局是不需要绘制的,而网易云进行了绘制,导致抽屉布局所在区域的像素点绘制了多次。

google官方在android.support.v4.widget包下有DrawerLayout.Java类。使用来实现抽屉布局的。该类在重写了drawChild方法:

@Override

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

final int height = getHeight();

// 判断是否是内容视图

final boolean drawingContent = isContentView(child);

int clipLeft = 0, clipRight = getWidth();

// 记录当前画布信息

final int restoreCount = canvas.save();

if (drawingContent) {

// 只有在绘制内容视图时才进行裁切

final int childCount = getChildCount();

for (int i = 0; i < childCount; i++) {

final View v = getChildAt(i);

if (v == child || v.getVisibility() != VISIBLE ||

!hasOpaqueBackground(v) || !isDrawerView(v) ||

v.getHeight() < height) {

// 如果child是内容视图/视图不可见/视图背景透明/不是抽屉视图/child高度小于父布局高度

// 则不做画布裁切

continue;

}

if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {

// 盒子在左侧时裁切的left和right

final int vright = v.getRight();

if (vright > clipLeft) clipLeft = vright;

} else {

// 盒子在右侧时裁切的的left和right

final int vleft = v.getLeft();

if (vleft < clipRight) clipRight = vleft;

}

}

// 裁切画布

canvas.clipRect(clipLeft, 0, clipRight, getHeight());

}

// 绘制子视图

final boolean result = super.drawChild(canvas, child, drawingTime);

// 回复到裁切之前的画布

canvas.restoreToCount(restoreCount);

}

drawChild方法在ViewGroup类的dispatchDraw方法内被调用,用来绘制子视图,DrawerLayout类通过重写该方法,因为在所有孩子视图绘制之前都会调用drawChild方法,但是这里只需要对内容区域视图做裁切,当绘制内容区域视图时,取得抽屉视图的位置信息,如果抽屉视图可见、背景为不透明、抽屉高度和父布局高度一致时,取得抽屉视图左、上、右、下边缘在canvas中的位置信息。接着进行裁切,将内容视图未被挡住的部分区域裁切出来,并把裁切完的canvas交由子View进行绘制,这样,内容区域只有在裁切后的区域才会绘制,其他区域不进行绘制。

待子View绘制完之后,恢复Canvas到裁切之前的状态,因为一个Window下的所有View都使用的是同一个Canvas,所以需要恢复状态给其他子View使用。

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记做整理一份资料。

需要的朋友可以**私信【学习】**我分享给你,希望里面的资料可以给你们一个更好的学习参考。

或者直接点击下面链接免费获取

Android学习PDF+架构视频+面试文档+源码笔记

  • 330页PDF Android学习核心笔记(内含上面8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT部分大厂面试题(有解析)

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

片转存中…(img-DLONCHN3-1727086101767)]

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

[外链图片转存中…(img-jwfWpXc3-1727086101767)]

  • Android BAT部分大厂面试题(有解析)

[外链图片转存中…(img-JJfMucmM-1727086101768)]

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值