性能优化09_布局优化及Hierarchy Viewer使用

Android性能优化汇总
优化思想:查看自己的布局,层次是否很深以及渲染比较耗时,然后想办法能否减少层级以及优化每一个View的渲染时间。
CPU的优化,从减轻加工View对象成Polygons和Texture来下手

如何找出里面没用的view呢?或者减少不必要的view嵌套。
工具:Hierarchy Viewer检测,通过View Hierarchy可以找到没有用的view,这些view根本就不会显示在屏幕上面,一旦触发测量和布局操作,就会拖累应用的性能表现。

一 Hierarchy Viewer使用

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

  2. 切换到Hierarchy Viewer窗口
    在这里插入图片描述

  3. 选中要查看布局的Activity,点击load the view hierarchy into the tree view
    在这里插入图片描述

  4. view Tree 中能看到整个布局视图,包括PhoneWindow的

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

  1. 问题:
  • Unable to get view server protocol version from device
    不显示的话,关闭CPU显示过度绘制,
  • Measure、LayoutDraw时间没有,不显示三个圆点
    开发者设置关闭、重新获取刷新一下、选择父控件、点击右上角按钮
    在这里插入图片描述

二 减少布局嵌套

  • 主要减少Mesure、Layout
    方法: merge 和ViewStub、RelativeLayout减少布局层级和加载

  • merge: 当我们的布局是用的FrameLayout的时候,我们可以把它改成merge
    可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)

  • ViewStub: 当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
    例如: 一个ListView用wrapcontent,优化前的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>

优化前Hierarchy显示(有红色、黄色警告)
在这里插入图片描述

ListView用MatchParent、Item使用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>

在这里插入图片描述
优化后,警告明显减少了(ListView本身的测量和绘制还是比较耗时的)

三 减少过度绘制

工具: 设置-> 开发人员选项-> 调试GPU过度绘制
**查看:**局域颜色越深,过度绘制越严重(要排除控件本身背景色的干扰)

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

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

 getWindow().setBackgroundDrawable(null);

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

优化前,在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();
    }
}

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值