前言
Hierarchy Viewer是一个内置在Android Device Monitor中的工具,它允许你查看Activity的布局层次结构以及每个View的属性和布局速度。Hierarchy Viewer可以帮助你发现布局层次结构导致的性能瓶颈,从而帮助你优化布局层次结构和减少过度绘制。
准备工作
在开始之前,我们需要先将设备连接到电脑,然后开启设备的开发者选项。具体操作是:进入设备的 设置 应用,找到并进入 开发者选项,点击开启 开启开发者选项、USB调试 和 USB安装。如下图所示:
启动Hierarchy Viewer
首先,在Android Studio中打开你的项目,在设备上运行你的应用。
然后,在Android Studio中选择 Tools > Android > Android Device Monitor,打开Android Device Monitor。如下图所示:
最后,在Android Device Monitor中选择 Window > Open Perspective… > Hierarchy View,点击OK,打开Hierarchy Viewer。如下图所示:
对于Android真机,Hierarchy Viewer右下角的Console会打印如下信息:
[2017-10-01 15:36:59 - hierarchyviewer]Unable to get view server version from device 160e94f3
[2017-10-01 15:36:59 - hierarchyviewer]Unable to get view server protocol version from device 160e94f3
[2017-10-01 15:37:00 - ViewServerDevice]Unable to debug device: mi_4lte-160e94f3
[2017-10-01 15:37:00 - hierarchyviewer]Missing forwarded port for 160e94f3
[2017-10-01 15:37:00 - hierarchyviewer]Unable to get the focused window from device 160e94f3
打印信息提示无法获取设备的View Server,因此无法在Android真机上使用Hierarchy Viewer。
引用Android官方的一句话:
For security reasons, HierarchyViewer does not work on production builds (for instance phones bought in store).
我们可以知道,出于安全的原因,Hierarchy Viewer不能用于商业设备。
解决Android真机不能使用的问题
针对Android真机不能使用Hierarchy Viewer的问题,Android官方提供了一个叫做 ViewServer 的类。通过使用这个类,你可以在任何设备上使用Hierarchy Viewer。GitHub仓库地址为:https://github.com/romainguy/ViewServer
ViewServer库的使用比较简单:
- 集成ViewServer库。
- 添加INTERNET权限。
- 注册需要查看的Activity。
示例代码如下所示:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewServer.get(this).addWindow(this);
}
@Override
protected void onResume() {
super.onResume();
ViewServer.get(this).setFocusedWindow(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ViewServer.get(this).removeWindow(this);
}
}
如果需要查看所有的Activity,那么需要在所有的Activity中添加代码。这样太麻烦,而且不好维护。我们可以注册一个 ActivityLifecycleCallbacks 监听器,在所有Activity的生命周期回调方法中统一添加代码。源码地址:https://github.com/chongyucaiyan/ViewServerDemo
首先,我们创建一个实现了ActivityLifecycleCallbacks接口的类,并在onActivityCreated()、onActivityResumed()和onActivityDestroyed()回调方法中添加ViewServer相关的代码。具体代码如下所示:
public class ActivityLifecycleCallbacksImpl implements Application.ActivityLifecycleCallbacks {
private Context mContext;
public ActivityLifecycleCallbacksImpl(Context context) {
mContext = context;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ViewServer.get(mContext).addWindow(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
ViewServer.get(mContext).setFocusedWindow(activity);
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
ViewServer.get(mContext).removeWindow(activity);
}
}
然后,我们需要在应用自定义的Application类中注册ActivityLifecycleCallbacks监听器。具体代码如下所示:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 如果是Debug版本,那么才注册ActivityLifecycleCallbacks监听器
if (BuildConfig.DEBUG) {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksImpl(this));
}
}
}
注意: 只有当应用是Debug版本时才注册ActivityLifecycleCallbacks监听器。这样,在不修改原来Activity代码的情况下,所有的Activity都可以使用Hierarchy Viewer了。
最后,重新运行应用,并重新打开Hierarchy Viewer。如下图所示:
可以看到,左边的Windows窗格列出了当前显示的Activity,右下角的Console窗格不再打印无法获取View Server的信息,Hierarchy Viewer启动成功了。
使用Hierarchy Viewer
选中左边的Windows窗格列出的当前显示的Activity,然后点击Activity上面的加载布局层次结构按钮 ,Activity的布局层次结构就在Tree View窗格中显示出来了。如下图所示:
可以看到,Hierarchy Viewer主要提供了如下几个窗格:
- View Properties 当你在Tree View窗格中选中一个View时,View Properties窗格就会显示这个View的各种属性。
- Tree View 显示Activity的布局层次结构的树视图。你可以使用鼠标拖动树视图,使用滚轮缩放树视图。每个节点显示了它的类名、ID名和它在父容器中的相对索引。
- Tree Overview 显示完整的Activity的布局层次结构的鸟瞰图。移动灰色矩形可以改变Tree View窗格中可见的内容。
- Layout View 显示布局的线框视图。当前选中的View的线框是红色的,它的父容器的线框是浅红色的。点击这里的View也会在Tree View窗格中选中它,反之亦然。
在Tree View窗格的上面有几个按钮比较常用。Tree View窗格中的布局层次结构是布局的快照,因此它不会自动更新。要更新该Activity的布局层次结构,可以点击重载布局层次结构按钮 。
要使View无效(请求系统在下次布局更新时调用onDraw()方法),先在Tree View窗格中选中一个View,然后点击使布局无效按钮 (这等同于调用了View的invalidate()方法)。
要请求View重新布局,可以点击请求布局按钮 。
要查看View的测量时间、布局时间、绘制时间和相对性能,先在Tree View窗格中选中一个父容器,然后点击获取布局时间按钮 。如下图所示:
你可以查看子View的测量时间、布局时间和绘制时间。每个子View都有三个点,可以是绿色、黄色或者红色。
- 左边的点 表示View的测量阶段。
- 中间的点 表示View的布局阶段。
- 右边的点 表示View的绘制阶段。
这些点的颜色表示该节点相对于其它节点的相对性能。
- 绿色 表示View的渲染速度比其它一半的View要快。
- 黄色 表示View的渲染速度比其它一半的View要慢。
- 红色 表示View是渲染速度最慢的View之一。
Hierarchy Viewer测量每个节点相对于其它节点的性能,因此在布局层次结构中总有红色节点。这并不一定意味着红色节点性能差,可能它只是该布局中渲染速度最慢的View。当Activity的渲染速度慢、性能差时,红色节点很有可能就是潜在的问题。
总结
Hierarchy Viewer允许你查看Activity的布局层次结构以及每个View的属性和布局速度,它可以帮助你发现布局层次结构导致的性能瓶颈,从而帮助你优化布局层次结构和减少过度绘制。
参考
- https://developer.android.com/studio/profile/hierarchy-viewer.html
- https://github.com/romainguy/ViewServer