最上面的路径就是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。
TraceView是 AndroidSdk中自带的数据采集和分析工具,一般来说通过TraceView,我们可以得到两种数据:
-
单次执行耗时的方法
-
执行次数多的方法
如何使用Traceview
要分析traceview,首先要得到一个 trace文件。获取trace文件有两种方式:
- DDMS中使用
在Android Device Monitor中选择相应的进程,并单击Start Method Profiling
按钮
然后对应用中需要监控的点进行操作
最后单击 Stop Method Profiling
按钮,会自动跳到TraceView师徒
- 在代码中加入调试语句
Debug.startMethodTracing();
…
Debug.stopMethodTracing();
系统会在SD卡中生成trace文件,将trace文件导出并用SDK中的Traceview打开即可。当然这需要我们为应用程序加上写权限。
然后我们就能得到trace文件。
接着我们来分析一下trace文件:
=======================================================================
一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升。
当然这只是布局优化的一方面。
在讲布局优化之前,我们先来学习两种布局优化的工具,分别是 Hierarchy Viewer和Android Lint
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的耗时。
一个合格的布局,它应该是层级合理的。即纵向多,横向少。
Android Lint是在ADT 16中提供的新工具,它是一个代码扫描工具,通过代码静态检查来发现代码出现的潜在问题,并给出优化建议。检查的范围主要有以下几点:
-
正确性:Correctness
-
安全性:Security
-
性能:Performance
-
可用性:Usablity
-
可达性:Accessiblility
-
国际化:Internationalization
其功能十分强大,这里我们只关注 XML布局检查,可以通过AS的 Analyze->Inspect Code 来配置检查的范围。
点击OK后,就会出现所有问题的采集,以及每个问题种类的个数:
通过点击每一项,我们就能知道哪里出现了问题,或者说哪里的代码/资源文件没有被引用到。
我们可以通过在 Setting -> Editor-> Inspections 中配置Lint检查的范围。
布局优化的方法有很多,主要包括 合理运用布局、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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
为了方便有学习需要的朋友,我把资料都整理成了视频教程(实际上比预期多花了不少精力)
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
- 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!
- 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。
加油,共勉。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
- 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!
- 我希望每一个努力生活的IT工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,没有人能随随便便成功。
加油,共勉。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!