使用Hierarchy Viewer分析优化布局性能

来源:互联网 发布:淘宝开店需要哪些软件 编辑:程序博客网 时间:2024/05/18 20:07

打开Hierachy Viewer

  • 配置环境变量为在真机上使用Hierarchy Viewer分析性能做准备
    将手机调整到开发者模式在这里就不罗嗦了,添加环境变量:
    ANDROID_HVPROTO
    ddm
    配置完成后,重启计算机
  • 打开Hierarchy Viewer进行分析
    在手机上打开想要调试的APP(正式打包的不行)
    到D:\android\sdk\tools路径下,双击monitor.bat文件,你可能会有疑惑不是hierarchyviewer.bat吗?没关系,仅仅是双击hierarchyviewer.bat depressed,如果提示在xx路径下面找不到jre之类的信息,把你jdk按照目录下的jre文件夹直接copy一份到指定的位置,再次启动即可。
    ![这里写图片描述]
    这里写图片描述
    选中要分析的APP,点击右上角的按钮。
    这里写图片描述
    如果没有出现红黄绿色的按钮和相关的测试数据,在主要显示区中选中某一个节点,点击右上角的一个三色的按钮,就ok了。

红黄绿含义和对布局性能分析的指导

当APP性能低下的时候,仅仅表明红色dot可能存在问题。由于这里的颜色值是一个相对值,总是会有一个最慢的节点,确保它应该是最慢的。

  • 如果red dot在一个叶子节点或者一个只有几个子节点的ViewGroup上,可能会存在一些问题。APP整体表现可能不坏,但是你要意识到那个节点为什么是红色的!可以使用Systrace或者 TraceView做进一步的分析。
  • 如果ViewGroup的Measure 是红色的,要分析一下它的子节点。
  • 如果View存在黄色甚至红色dot,可能在手机上的运行效率并不慢,可能是由于view的数目过多造成的。可以使用Systrace或者 TraceView做进一步的分析。
  • 如果一个层级结构的根节点measure dot是红色的,layout dot是红色的,draw dot是黄色的,这是一种非常典型的情况,因为它是所有节点的根节点。
  • 如果一个有20+ view的层级结构中,一个叶子节点draw dot是红色的,那肯定是问题,检查一下它的onDraw方法。

使用Hierarchy Viewer的简单例子

slow.xml文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="100dp"    android:orientation="horizontal" >    <ImageView        android:id="@+id/iv"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:contentDescription="@null"        android:src="@drawable/ic_launcher" />    <LinearLayout        android:id="@+id/ll_right"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="4"        android:orientation="vertical" >        <TextView            android:id="@+id/tv_title"            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="1"            android:background="#ff0000"            android:text="This is Title!" />        <TextView            android:id="@+id/tv_content"            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="4"            android:background="#00ff00"            android:text="This is Content!" />    </LinearLayout></LinearLayout>

MainActivity代码如下:

public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.slow);    }    }

使用Hierarchy Viewer分析如下:
这里写图片描述
这里在强调一下这里都是相对值,单纯的看Measure/Layout/Draw没有意义。由于手机或者PC CPU负载的变化每一次获取的图片都可能不一样,可以通过点击上图的三色按钮进行刷新。这里发现id/ll_right的Measure是红色的,这里符合提到的第一条和第二条,分析一下id/ll_right的子节点, 应该很快发现,Android中不提倡使用weight,咱们这里使用了weight的嵌套,更是大忌。官方文档是这么说的

It is a common misconception that using the basic layout structures leads to the most efficient layouts. However, each widget and layout you add to your application requires initialization, layout, and drawing. Furthermore, ***nesting several instances of LinearLayout that use the layout_weight parameter can be especially expensive as each child needs to be measured twice.*** This is particularly important when the layout is inflated repeatedly, such as when used in a ListView or GridView.

使用layout_weight参数的多级嵌套LinearLayout,每一个孩子节点需要测量两次。
优化一下,修改一下布局参数:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="100dp"    android:orientation="horizontal" >    <ImageView        android:id="@+id/iv"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:contentDescription="@null"        android:src="@drawable/ic_launcher" />    <TextView        android:id="@+id/tv_title"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/iv"        android:background="#ff0000"        android:text="This is Title!" />    <TextView        android:id="@+id/tv_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_below="@id/tv_title"        android:layout_toRightOf="@id/iv"        android:background="#00ff00"        android:text="This is Content!" /></RelativeLayout>

MainActivity代码如下:

package com.example.hierarchyviewdemo;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.DisplayMetrics;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.improved);        final ImageView iv = (ImageView) findViewById(R.id.iv);        RelativeLayout.LayoutParams ivParams = (RelativeLayout.LayoutParams) iv                .getLayoutParams();        ivParams.width = getScreenWidth(this) / 5;        ivParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;        final TextView titleView = (TextView) findViewById(R.id.tv_title);        RelativeLayout.LayoutParams titleParams = (RelativeLayout.LayoutParams) titleView                .getLayoutParams();        titleParams.width = RelativeLayout.LayoutParams.MATCH_PARENT;        titleParams.height = dip2px(this, 100) / 5;    }    public static int getScreenHeight(Activity packageContext) {        DisplayMetrics metrics = new DisplayMetrics();        packageContext.getWindowManager().getDefaultDisplay()                .getMetrics(metrics);        return metrics.heightPixels;    }    public static int getScreenWidth(Activity packageContext) {        DisplayMetrics metrics = new DisplayMetrics();        packageContext.getWindowManager().getDefaultDisplay()                .getMetrics(metrics);        return metrics.widthPixels;    }    public static int dip2px(Context context, float dipValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (dipValue * scale + 0.5f);    }}

看一下效果:

这里写图片描述

这里分析很粗错,仅仅起到一个抛砖引玉的作用,希望能给大家有点引导作用。

翻译地址

https://developer.android.com/tools/performance/hierarchy-viewer/profiling.html#InterpretingResults
http://developer.android.com/training/improving-layouts/optimizing-layout.html#Inspect

1 0
原创粉丝点击