性能优化06_Hierarchy Viewer使用及布局优化

Android性能优化汇总
CPU的优化,从减轻加工View对象成Polygons和Texture来下手
View Hierarchy中包涵了太多的没有用的view,这些view根本就不会显示在屏幕上面,一旦触发测量和布局操作,就会拖累应用的性能表现。

如何找出里面没用的view呢?或者减少不必要的view嵌套。
工具:Hierarchy Viewer检测

一 Hierarchy Viewer使用

找不到工具的,Android Monitor路径:打开sdk目录下的tool文件夹中monitor.bat

三个圆点分别代表:测量、布局、绘制三个阶段的性能表现。
1)绿色:渲染的管道阶段,这个视图的渲染速度快于至少一半的其他的视图。
2)黄色:渲染速度比较慢的50%。
3)红色:渲染速度非常慢。

二 常见的布局优化

优化思想:查看自己的布局,层次是否很深以及渲染比较耗时,然后想办法能否减少层级以及优化每一个View的渲染时间。

1 merge 和ViewStub、RelativeLayout减少布局层级和加载

  • merge: 当我们的布局是用的FrameLayout的时候,我们可以把它改成merge
    可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)
  • ViewStub: 当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
    例如一个列表,优化前的item如下:
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:paddingBottom="@dimen/chat_padding_bottom">

    <ImageView
        android:id="@+id/chat_author_avatar"
        android:layout_width="@dimen/avatar_dimen"
        android:layout_height="@dimen/avatar_dimen"
        android:layout_margin="@dimen/avatar_layout_margin" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#78A"
            android:background="@android:color/white"
            android:orientation="horizontal">

            <TextView xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:padding="@dimen/narrow_space"
                android:gravity="bottom"
                android:id="@+id/chat_author_name" />

            <TextView xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:textStyle="italic"
                android:padding="@dimen/narrow_space"
                android:id="@+id/chat_datetime" />
        </RelativeLayout>

        <TextView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/narrow_space"
            android:background="@android:color/white"
            android:id="@+id/chat_text" />
    </LinearLayout>
</LinearLayout>

使用RelativeLayout优化后

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/chat_author_avatar"
        android:layout_width="@dimen/avatar_dimen"
        android:layout_height="@dimen/avatar_dimen"
        android:src="@drawable/alex" />

    <TextView
        android:id="@+id/chat_author_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/chat_author_avatar"
        android:paddingLeft="@dimen/narrow_space"
        android:text="XXX" />

    <TextView
        android:id="@+id/chat_datetime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingRight="@dimen/narrow_space"
        android:text="AAA"
        android:textStyle="italic" />

    <TextView
        android:id="@+id/chat_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/chat_datetime"
        android:layout_toRightOf="@id/chat_author_name"
        android:paddingBottom="@dimen/chat_padding_bottom"
        android:paddingLeft="@dimen/narrow_space"
        android:text="BBB" />

</RelativeLayout>

2 背景经常容易造成过度绘制。

手机开发者选项里面找到工具:Debug GPU overdraw 可以看到过度绘制的局域颜色变深

**解决的办法:**将主题添加的背景去掉

3 自定义控件通过裁剪处理过度绘制。

优化前,在Canvas上重复绘制:

public class CardsView extends View {

    //图片与图片之间的间距
    private int mCardSpacing = 150;
    //图片与左侧距离的记录
    private int mCardLeft = 10;

    private List<Card> mDroidCards = new ArrayList<>();

    private Paint paint = new Paint();

    public CardsView(Context context) {
        super(context);
        initCards();
    }

    public CardsView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initCards();
    }

    public CardsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initCards();
    }

    /**
     * 初始化卡片集合
     */
    protected void initCards() {
        Resources res = getResources();
        mDroidCards.add(new Card(res, R.drawable.alex, mCardLeft));

        mCardLeft += mCardSpacing;
        mDroidCards.add(new Card(res, R.drawable.claire, mCardLeft));

        mCardLeft += mCardSpacing;
        mDroidCards.add(new Card(res, R.drawable.kathryn, mCardLeft));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (Card c : mDroidCards) {
            drawCard(canvas, c);
        }
        invalidate();
    }

    private void drawCard(Canvas canvas, Card c) {
        canvas.drawBitmap(c.bitmap, c.x, 0f, paint);
    }


}

通过裁剪canvas优化,只绘制显示的区域,注意canvas的恢复

public class OptimizationCardsView extends View {

    //图片与图片之间的间距
    private int mCardSpacing = 150;
    //图片与左侧距离的记录
    private int mCardLeft = 10;

    private List<Card> mDroidCards = new ArrayList<>();

    private Paint paint = new Paint();

    public OptimizationCardsView(Context context) {
        super(context);
        initCards();
    }

    public OptimizationCardsView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initCards();
    }

    public OptimizationCardsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initCards();
    }

    /**
     * 初始化卡片集合
     */
    protected void initCards() {
        Resources res = getResources();
        mDroidCards.add(new Card(res, R.drawable.alex, mCardLeft));

        mCardLeft += mCardSpacing;
        mDroidCards.add(new Card(res, R.drawable.claire, mCardLeft));

        mCardLeft += mCardSpacing;
        mDroidCards.add(new Card(res, R.drawable.kathryn, mCardLeft));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < mDroidCards.size() - 1; i++) {
            drawDroidCard(canvas, mDroidCards, i);
        }

        drawLastDroidCard(canvas, mDroidCards.get(mDroidCards.size() - 1));
        invalidate();
    }

    /**
     * 绘制最后一个Card
     *
     * @param canvas
     * @param c
     */
    private void drawLastDroidCard(Canvas canvas, Card c) {
        canvas.drawBitmap(c.bitmap, c.x, 0f, paint);
    }

    /**
     * 绘制Card
     *
     * @param canvas
     * @param mDroidCards
     * @param i
     */
    private void drawDroidCard(Canvas canvas, List<Card> mDroidCards, int i) {
        Card c = mDroidCards.get(i);
        canvas.save();
        canvas.clipRect(c.x, 0f, mDroidCards.get(i + 1).x, c.height);
        canvas.drawBitmap(c.bitmap, c.x, 0f, paint);
        canvas.restore();
    }
}

发布了224 篇原创文章 · 获赞 69 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/baopengjian/article/details/103998676
今日推荐