文集目录
ps:喜欢的点赞哦 android性能跟踪分析工具系列 - 目录
Hierarchy Viewer工具提供了一个可视化界面显示布局的层次结构,让我们可以进行调试,从而优化界面布局结构。
不要小看这个工具啊,这可是必备工具啊,遥想当年,因为界面布局复杂,我写的个人中心界面可是差不多2s 才显示出来啊,优化起来那叫一个痛苦啊,奈何 UI 给的设计图太他妈复杂了,UI 自己都是瞎往上拖控件,他自己都不知道为了啥,就是知道你开发就是不能改,那排版反人类啊,好在现在有了 ConstraintLayout 约束布局,这个用好了简直利器啊,一般人我可不告诉他哈。
闲话不多说,先来看看 Hierarchy Viewer 长啥样子
整个工具分3个部分,左边的是布局层次图,使用滚轮可以放大缩小的,点击具体的 view 是可以查看view 的3 measu/layout/draw 方法的耗时的,颜色部分,绿色是计算很快,黄色是计算速度在所有的view 中居中,50%的水平,红色是计算很慢,是需要严重关注的。
右上角的是缩略图不多说,右下角的是我们在层次图中选中的 view 在整个界面的位置,红框占中的就是,这里我选的是根视图,所以把整个界面都包括进来了
注意啊,我们刚刚进来是需要选中根视图,然后点击我在上面用红框圈中的按钮,点一下就是重新计算,注意点一下就行,第一次计算才是页面启动时的用时,你再点都是刷新页面的用时了
如何启动
好了上面简单说了下这个工具我们看哪,现在就来说说这个工具怎么打开
打开 Android devices trace ,之前介绍过了
在 DDMS 中我们点击 Hierarchy Viewer ,然后选择我们需要查看的进程就中的具体的某个页面,再点这个Hierarchy Viewer按钮
如何优化布局层次
好了, 这个工具打开和使用都很简单,主要的我们需要借助这个工具查看我们的页面布局水平,要是发现效率低,必须优化的,所以本篇的重点就来了,就是如何优化布局层次,方法如下:
- 线性布局比相对布局有布局优势
在布局层级相同的情况下,相对布局比线性布局会多跑 measu 方法,效率第一点。这点效率优势比少一层布局层级来说要轻微许多。 - 使用ConstraintLayout 约束布局
约束布局的 view 相互定位方式真的太强大了,极端情况下,我们的内容布局用一层就可以 - 使用 ViewStub
在布局中有的 layout 我们可能很少显示他,这样 ViewStub ,stubView在不显示时是不会参与布局相关计算的,属于延迟加载的一种了。 - 使用 space 标签
space 标签继承自 view,但是把 draw方法做了空实现,所以不会进行绘制 - 使用merge减少无用的父布局
merge使用起来有很多限制,具体使用机会比较少。
下面我说下比较容易忘的
ViewStub的使用
ViewStub是一个用于在运行时加载布局资源、不可见、宽高为0的View,在布局文件中使用它只是用于占位,在代码中没有手动加载它时,并不会影响页面的测量、绘制、显示效率,在代码中通过inflate加载ViewStub时,ViewStub会用在布局文件中为其指定的布局文件来代替它自身,通过前面的解释可想而知,ViewStub只能够被inflate一次,一旦加载后ViewStub对象就会被置为空;ViewStub标签有对应的java类ViewStub.java,通过阅读源码可以发现,确实在初始化的时候设置为隐藏、不绘制、宽高为0,并且它复写了View的dispatchDraw和draw方法,这俩方法是空方法,没有调用super的方法,也没有执行自己的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
mViewStub = (ViewStub) findViewById(R.id.view_show);
}
public void showViewStub(View view) {
// mSHowView是 vie2wstub 显示之后获得的 view 对象
if (mSHowView == null) {
mSHowView = mViewStub.inflate();
return;
}
mSHowView.setVisibility(View.VISIBLE);
}
恩,viewstub 使用很简单,记得我们在 inflate() 之后会返回实体的 view,之后我们再显示隐藏,操作的都是这个 view 了
space 标签
space标签可以只在布局文件中占位,不绘制,Space标签有对应的java类Space.java,通过阅读源码可以发现,它继承至View.java,并且复写了draw方法,该方法为空,既没有调用父类的draw方法,也没有执行自己的代码,表示该类是没有绘制操作的,但onMeasure方法正常调用,说明是有宽高的。这可是神器啦。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center"
android:text="TextView 1"
android:textColor="@android:color/black"
android:textSize="28dp"
android:background="@android:color/darker_gray"/>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/black"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center"
android:text="TextView 2"
android:textColor="@android:color/black"
android:textSize="28dp"
android:background="@android:color/darker_gray"/>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center"
android:text="TextView 3"
android:textColor="@android:color/black"
android:textSize="28dp"
android:background="@android:color/darker_gray"/>
</LinearLayout>
效果图:
给第一个 space 设置背景色,实际是不会生效的,别忘了 space 的 draw方法可是空的