视图绘制优化实战

166 阅读1分钟

视图绘制回顾

测量:确定大小

布局:确定位置

绘制:绘制视图

性能瓶颈

每个阶段耗时

自顶而下的遍历

触发多次

布局层级及复杂度

准则

减少View树层级

宽而浅,避免窄而深

不嵌套使用RelativeLayout

不在嵌套LinearLayout中使用weight

merge标签:减少一个层级,只能用于根View

ConstraintLayout

实现几乎完全扁平化布局

构建复杂布局性能更高

具有RelativeLayout和LinearLayout特性

过度绘制

一个像素最好只被绘制一次

调试GPU过度绘制

蓝色可接受

避免过度绘制方法

去掉多余背景色,减少复杂shape使用

避免层级叠加

自定义View使用clipRect屏蔽被遮盖View绘制

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // Don't draw anything until all the Asynctasks are done and all the DroidCards are ready.
        if (mDroids.length > 0 && mDroidCards.size() == mDroids.length) {
            // Loop over all the droids, except the last one.
            int i;
            for (i = 0; i < mDroidCards.size() - 1; i++) {

                mCardLeft = i * mCardSpacing;
                canvas.save();
                // 指定绘制区域

                canvas.clipRect(mCardLeft,0,mCardLeft+mCardSpacing,mDroidCards.get(i).getHeight());

                // Draw the card. Only the parts of the card that lie within the bounds defined by
                // the clipRect() get drawn.
                drawDroidCard(canvas, mDroidCards.get(i), mCardLeft, 0);

                canvas.restore();
            }

            // Draw the final card. This one doesn't get clipped.
            drawDroidCard(canvas, mDroidCards.get(mDroidCards.size() - 1),
                    mCardLeft + mCardSpacing, 0);
        }

        // Invalidate the whole view. Doing this calls onDraw() if the view is visible.
        invalidate();
    }

其他技巧

Viewstub:高效占位符、延迟初始化

onDraw中避免:创建大对象、耗时操作

TextView优化