UI绘制优化

CPU与GPU

CPU 的任务繁多,做逻辑计算外,还要做内存管理、显示操作,因此
在实际运算的时候性能会大打折扣,在没有 GPU 的时代,不能显示复
杂的图形,其运算速度远跟不上今天复杂三维游戏的要求。即使 CPU
的工作频率超过 2GHz 或更高,对它绘制图形提高也不大。这时 GPU
的设计就出来了, CPU 的控制器较为复杂,擅长各种复杂的逻辑运算,但不擅长数学尤其是浮点运算。
简单来说就是CPU将图形的计算公式传给GPU,也可理解为显卡,然后GPU拿到这个公式后就开始矢量图的绘制工作,Android 系统每隔 16ms 发出 VSYNC 信号 (1000ms/60=16.66ms) ,触发对 UI 进行渲染, 如果每次渲染都成功这样就能够达到流畅的画面所需要的 60fps ,为了能够实现 60fps ,这意味着计算渲染的大多数操作都必须在 16ms 内完成。如果很多帧都没有在这个时间内绘制完成,就会出来视觉上的卡顿现象。这也是60Hz 刷新频率由来。

过度绘制

概念:

GPU的绘制过程,类似于装修刷墙,一层一层的进行,并且16ms刷一次,每刷一遍就是一个图层,这样就会有图层覆盖的情况,下边的图层用户看不到,但其实GPU也已经进行了绘制。

过度绘制出现的原因

  1. 自定义控件中的 onDraw 方法做了多重绘制
  2. 布局层次太深,例如xml文件使用了迷之缩进,布局层叠太多,用户看不到的区域也进行了绘制,导致耗时增加

过渡绘制查看

开发者工具打开调试GPU过渡绘制
过度绘制查看

可以看到上边有很多颜色,颜色越浅,说明过度绘制越少,

  1. 蓝色部分,过渡绘制一次,就是无过渡绘制,只有一层
  2. 淡绿色 过渡绘制两次,说明有两层
  3. 淡红色 过度绘制三次
  4. 深红 过度绘制四次及以上

然后就各个击破进行优化就好了

过度绘制优化

  1. 减少背景重复
去掉单个activity的主题设置的属性
可以在setContentView之前getWindow().setBackgroundDrawable(null);

去掉所有activity主题设置中的属性
直接在styles.xml中设置<item name="android:windowBackground">@null</item>

  1. 使用裁减减少控件之间的重合部分
  2. 注意点:
    1.能在一个平面显示的内容,尽量只用一个容器
    2.尽可能把相同的容器合并merge
    3.能复用的代码,用include处理,可以减少GPU重复工作

hierarchy view 查看布局结构图

在你的AndroidSDK的安装目录找到 Android\sdk\tools\monitor.bat,双击运行(运行前先在模拟器中启动项目,真机好像不太好使),切换到Hierarchy View ,找到自己的要查看的页面

在这里插入图片描述

view层级

这样就可以看到你的当前页面每个布局下一共有几层view了,试图减少view的层级可以提高GPU的渲染效率

扫描二维码关注公众号,回复: 8670389 查看本文章

自定义view裁剪被遮挡布局

public class DroidCardsView extends View {

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

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

    private Paint paint = new Paint();

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

    public DroidCardsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initCards();
    }



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

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

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

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

        invalidate();
    }

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

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

    /**
     * 绘制DroidCard
     * @param canvas
     * @param mDroidCards
     * @param i
     */
    private void drawDroidCard(Canvas canvas,List<DroidCard> mDroidCards,int i) {
        DroidCard c = mDroidCards.get(i);
        canvas.save();//备份画布
        
        //裁剪画布
        canvas.clipRect((float)c.x,0f,(float)(mDroidCards.get(i+1).x),(float)c.height);
        canvas.drawBitmap(c.bitmap,c.x,0f,paint);
        
        canvas.restore();//释放画布
    }
}
发布了316 篇原创文章 · 获赞 63 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/ytfunnysite/article/details/100118340
今日推荐