Android 绘制性能优化(1)

本文详细介绍了如何在Android中使用Systrace进行应用性能追踪,包括命令行和代码中的应用,以及如何通过Chrome分析Systrace结果。此外,还讲解了TraceView的数据采集和分析,以及布局优化工具HierarchyViewer和AndroidLint的使用。
摘要由CSDN通过智能技术生成

在这里插入图片描述

最上面的路径就是Systrace生成html的路径。

第二行就是跟踪的时间,可以自己设置。

点击ok后,就会去追踪当前应用。

2. 用命令行使用Systrace

Android提供一个Python脚本文件systrace.py,它位于Android SDK目录 /tools/systrace中,我们可以使用以下命令来使用Systrace:

C:>cd C:\Users\msn\AppData\Local\Android\Sdk\platform-tools\systrace

C:\Users\msn\AppData\Local\Android\Sdk\platform-tools\systrace>python systrace.py --time=10 -o newtrace.html sched gfx view wm

然后我的就提示:Systrace does not support Python 3.7. Please use Python 2.7.

也就是说Android Studio通过命令行使用Python查看Systrace,要用2.7版本的…

3. 在代码中使用Systrace

可以使用Trace类对应用中的具体活动进行追踪。Android源码中也引入了Trace类,为了展示得更加直观,这里RecyclerView得源码:

void scrollStep(int dx, int dy, @Nullable int[] consumed) {

this.startInterceptRequestLayout();

this.onEnterLayoutOrScroll();

//这里开始使用了Trace进行追踪

TraceCompat.beginSection(“RV Scroll”);

this.fillRemainingScrollValues(this.mState);

int consumedX = 0;

int consumedY = 0;

if (dx != 0) {

consumedX = this.mLayout.scrollHorizontallyBy(dx, this.mRecycler, this.mState);

}

if (dy != 0) {

consumedY = this.mLayout.scrollVerticallyBy(dy, this.mRecycler, this.mState);

}

//这里开始暂停了Trace追踪

TraceCompat.endSection();

this.repositionShadowingViews();

this.onExitLayoutOrScroll();

this.stopInterceptRequestLayout(false);

if (consumed != null) {

consumed[0] = consumedX;

consumed[1] = consumedY;

}

}

TraceCompat类对 Trace类进行了封装,其中 beginSection()endSection()方法之间的代码会被追踪,endSection() 只会结束最近的 beginSection(),因此要保证这个两个方法调用的次数要相同。

用Chrome分析Systrace

通过前面的方法生成了trace.html文件后,我们用Chrome打开它,如下图所示:

在这里插入图片描述

我们可以使用W、S键进行放大和缩小,A、D键进行左右移动。接下来介绍上图中的各个区域:

1.Alert区域

这个区域会标记性能有问题的点,单击叹号图标就是查看某一个Alert的问题描述,如下图所示:

在这里插入图片描述

这里指出:Scheduling delay说明这个处理特定时间片的线程很长时间没有被CPU调度,因此这个线程花了很久才完成。为什么会出现这种状况呢?可能是因为开启了太多的线程和UI线程竞争CPU资源,导致UI线程迟迟不能执行。

2.CPU区域

CPU区域,每一行代表一个CPU核心和它执行任务的时间片,放大后会看到每个色块代表一个执行过程,色块的长度表示执行时间。

在这里插入图片描述

CPU0主要执行adbb线程和InputReader线程,CPU 1主要执行surfaceflinger线程和ordinartorlayout进程中的RnderThread线程,我们单击每个色块,都能看到它做了什么事情,用了多久。

3. 应用区域

在这里插入图片描述

Systrace会给出应用中的Frames分析,每一帧就是一个F圈圈,F圈圈有三种颜色,绿色表示渲染流畅,黄色和红色则代表渲染的时间超过了16ms,红色更严重一点。图中的红色F点击后会告诉我们原因。

4. Alerts总体分析

单击最右边的Alerts按钮会给出Alert的总体分析:

在这里插入图片描述

Alerts会给出Alert类型,以及出现的次数。有了这些总体的分析,方便开发者对该间断的绘制性能有一个大概的了解,便于进行下一步分析。

由于Systrace是以系统的角度返回一些信息的,只能为我们提供一个概览,它的深度是有限的,我们可以用它来进行粗略的检查,以便了解大概的情况,但是如果还要分析的更加详细,比如要找到是什么让CPU繁忙,某些方法的调用次数等,则还要借助另一个工具 Traceview。

1.4 Traceview


TraceView是 AndroidSdk中自带的数据采集和分析工具,一般来说通过TraceView,我们可以得到两种数据:

  1. 单次执行耗时的方法

  2. 执行次数多的方法

如何使用Traceview

要分析traceview,首先要得到一个 trace文件。获取trace文件有两种方式:

  1. DDMS中使用

在Android Device Monitor中选择相应的进程,并单击Start Method Profiling 按钮

然后对应用中需要监控的点进行操作

最后单击 Stop Method Profiling 按钮,会自动跳到TraceView师徒

  1. 在代码中加入调试语句

Debug.startMethodTracing();

Debug.stopMethodTracing();

系统会在SD卡中生成trace文件,将trace文件导出并用SDK中的Traceview打开即可。当然这需要我们为应用程序加上写权限。

然后我们就能得到trace文件。

接着我们来分析一下trace文件:

2.布局优化

=======================================================================

一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升。

当然这只是布局优化的一方面。

在讲布局优化之前,我们先来学习两种布局优化的工具,分别是 Hierarchy Viewer和Android Lint

2.1 Hierarchy Viewer


Hierarchy Viewer是Android SDK自带的可视化的调试工具,用来检查布局嵌套和绘制的时间

我们通过 Android Device Monitor,在其中选择Hierarchy Viewer如下图:

在这里插入图片描述

打开后会给出一个Hierarchy Viewer窗口,在Hierarchy Viewer窗口中有4个子窗口,它们的作用如下:

  • Windows

当前设备所有界面列表

  • Tree View

将当前Activity 的所有View的层次按照高层到低层从左到右显示出来

  • Tree Overview

全局概览,以缩略的形式显示

  • Layout View

整体布局图,以手机屏幕上真是的位置呈现出来。

使用注意:

在Android的官方文档中提到:

To preserve security, Hierarchy Viewer can only connect to devices running a developer version of the Android system.

即:出于安全考虑,Hierarchy Viewer只能连接Android开发版手机或是模拟器(准确地说,只有ro.secure参数等于0且ro.debuggable等于1的android系统)。Hierarchy Viewer在连接手机时,手机上必须启动一个叫View Server的客户端与其进行socket通信。而在商业手机上,是无法开启View Server的,故Hierarchy Viewer是无法连接到普通的商业手机。

所以我们在使用Android Device Monitor去连接真机/没有配置的模拟器 会提示: Unable to get view server version from device xxxx....

网上有很多教程,主要是通过Android逆向去替换系统文件,让系统通过可以调试的验证。

这边我的做法是使用 ViewServer的开源框架,在导入后,在Activity中的使用方法是:

public class MyActivity extends Activity {

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Set content view, etc.

ViewServer.get(this).addWindow(this);

}

public void onDestroy() {

super.onDestroy();

ViewServer.get(this).removeWindow(this);

}

public void onResume() {

super.onResume();

ViewServer.get(this).setFocusedWindow(this);

}

}

然后再去重新打开Hierarchy Viewer,在手机中打开使用这个代码的Activity就能看到层级结构了:

在这里插入图片描述

在我们开发中加入这些代码,当界面完成时,我们可以将这些调试的代码注释掉。

通过单击每个view,我们可以知道view的 layout、mesure、draw的耗时。

一个合格的布局,它应该是层级合理的。即纵向多,横向少。

2.2 Android Lint


Android Lint是在ADT 16中提供的新工具,它是一个代码扫描工具,通过代码静态检查来发现代码出现的潜在问题,并给出优化建议。检查的范围主要有以下几点:

  • 正确性:Correctness

  • 安全性:Security

  • 性能:Performance

  • 可用性:Usablity

  • 可达性:Accessiblility

  • 国际化:Internationalization

其功能十分强大,这里我们只关注 XML布局检查,可以通过AS的 Analyze->Inspect Code 来配置检查的范围。

在这里插入图片描述

点击OK后,就会出现所有问题的采集,以及每个问题种类的个数:

在这里插入图片描述

通过点击每一项,我们就能知道哪里出现了问题,或者说哪里的代码/资源文件没有被引用到。

我们可以通过在 Setting -> Editor-> Inspections 中配置Lint检查的范围。

2.3 布局优化方法


布局优化的方法有很多,主要包括 合理运用布局、Inculde、Merge和ViewStub。

1.合理运用布局

这个比较笼统。举个例子:

在布局很复杂时,合理运用 RelativeLayout可以来替代 LinearLayout,能减少很多层布局。

但是如果嵌套很多,使用 LinearLayout,性能要比 RelativeLayout要好。

这个还是要实际开发中,我们借助 Hierarchy Viewer等工具去判断。

2.用Include来进行布局的复用

这个比较常见。我们在项目中经常会好多个页面用到同一个View,比如说顶部栏、底部栏。我们就可以使用 <include>标签来进行复用。

3.用Merge标签去除多余层级

Merge意味着合并,在合适的场景使用Merge标签可以减少多余的层级。

<Merge> 一般和 <include>复用。 不如这么说,使用include并没有怎么照顾到性能而更多的是代码的复用性。

真正让 <include>在性能上有意义的就是 Merge标签。具体用法之前讲过,这里不讲了。

merge标签最好是替代 FrameLayout或者布局方向一致的LinearLayout

4.使用ViewStub来提高加载速度

在XML中我们有时候会用到 GONE或者INVISIBLE 来隐藏一个View,但是这样其实效率不高,因为系统仍然会解析他们。

可以使用 ViewStub来解决这一个问题。ViewStub是一个轻量级的View,不可见且不占据布局位置。

当ViewStub调用 inflate()或设置可见时,系统会加载 ViewStub指定的布局,然后将这个布局添加到ViewStub中,在对ViewStub调用 inflate方法或者设置可见之前,它是不占布局空间和系统资源的。它主要的目的是为目标视图占用一个位置。

所以使用ViewStub可以调高界面初始化的性能,从而提高界面的加载速度。

我们在xml中代码加入:

<ViewStub

android:id=“@+id/viewstub”

android:layout_width=“match_parent”

android:layout_height=“40dp”

android:layout=“@layout/titlebar”/>

然后再代码中使用:

ViewStub viewstub = findViewById(R.id.viewstub);

viewstub.infate();

viewstub.setVisibility(View.VISIBLE);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

为了方便有学习需要的朋友,我把资料都整理成了视频教程(实际上比预期多花了不少精力)

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!
  • 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。

加油,共勉。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!
  • 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。

加油,共勉。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值