设为首页 收藏本站 662p开源网
开启辅助访问 切换到宽版

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

切换风格 立即注册 找回密码

安卓教程网

查看: 10661|回复: 3

布局渲染笔记

[复制链接]
发表于 2019-5-21 14:30:07 | 显示全部楼层 |阅读模式
更多
CPU  处理逻辑计算和内存管理,显示操作。
GPU  CPU无法显示复杂的图形,GPU用于显示复杂图形,分担CPU的任务
xml布局到屏幕的显示流程:xml 通过 LayoutInflater 加载到内存中,然后经过CPU计算处理为多维图形,在通过 OpenGL 调用GPU,GPU对图形进行栅格化显示到屏幕上,此时如果上面流程在16毫秒内完成,则直接显示到显示器,如果没能完成,则垂直同步等待下一帧完成。
由于人类的眼睛看到画面之帧率高于每秒约10-12帧的时候,就会认为是连贯的;
对于有声电影的拍摄和播放帧率均为每秒24帧,对人是可以接受的,但是早期的高动态电子游戏帧率如果少于每秒30帧的话就会不连贯,因为没有动态模糊使流畅度降低,在于手机交互的过程中,如果触摸反馈60帧以下人是可以感觉出来的,60帧以上不能察觉变化,当手机上帧率低于60fps的时候会感觉画面的卡顿和迟滞现象;
android系统每隔16ms发出信号,触发对UI进行渲染,如果每次渲染都成功,就能达到流程的画面所需要的60fps,为了能够实现60fps,这意味着计算渲染的太多数操作都必须在16ms内完成。
当一帧画面渲染时间超过16ms的时候,垂直同步机制(每隔16ms刷新帧率)会让显示器硬件等待GPU完成栅格化渲染操作,这样会让一帧画面多停留16ms甚至更多,这样就造成了用户看起来画面停顿。
优化:
  CPU 减少xml转换成对象的时间,比如减少层级
  GPU 减少重复绘制
GPU的绘制过程根据CPU传递的指令来绘制,16ms绘制一次,指令来了就绘制,哪怕是同样的绘制指令,如果层次太深,用户看不到的区域也会被绘制,以及自定义控件中,onDraw方法做了过多的绘制。
Android手机开发者选项中,打开GPU过度绘制调试,蓝色 表示绘制了一次,淡绿色表示两次,淡红色表示三次,深红色表示四次。
注意:Android的Theme-主题中,是自带背景的,可以设置windowBackground为null
下面是一个过度绘制的离职,注释部分为过度绘制,打开部分为优化后的绘制,打开GPU调试后运行查看过度绘制区域,作比较
  1. import android.content.Context;
  2. import android.content.res.Resources;
  3. import android.graphics.Canvas;
  4. import android.graphics.Paint;
  5. import android.util.AttributeSet;
  6. import android.view.View;

  7. import java.util.ArrayList;
  8. import java.util.List;

  9. import androidx.annotation.Nullable;

  10. public class DroidCardsView extends View {

  11.     private int mCardSpacing = 150;//图片间隔
  12.     private int mCardLeft = 50;//图片左侧距离
  13.     private List<DroidCard> mDroidCards = new ArrayList<>();
  14.     private Paint paint = new Paint();

  15.     public DroidCardsView(Context context) {
  16.         super(context);
  17.         initCards();
  18.     }

  19.     public DroidCardsView(Context context, @Nullable AttributeSet attrs) {
  20.         super(context, attrs);
  21.         initCards();
  22.     }

  23.     private void initCards(){
  24.         Resources res = getResources();
  25.         mDroidCards.add(new DroidCard(res,R.mipMap.testpic1,mCardLeft));
  26.         mCardLeft += mCardSpacing;
  27.         mDroidCards.add(new DroidCard(res,R.mipmap.testpic2,mCardLeft));
  28.         mCardLeft += mCardSpacing;
  29.         mDroidCards.add(new DroidCard(res,R.mipmap.testpic1,mCardLeft));
  30.         mCardLeft += mCardSpacing;
  31.         mDroidCards.add(new DroidCard(res,R.mipmap.testpic2,mCardLeft));
  32.     }

  33.     @Override
  34.     protected void onDraw(Canvas canvas) {
  35.         super.onDraw(canvas);
  36. //        for (DroidCard card : mDroidCards) {
  37. //            drawDroidCard(canvas,card);
  38. //        }
  39. //        invalidate();

  40.         for (int i = 0;i < mDroidCards.size() -1;i++) {//最后一张不裁剪
  41.             drawDroidCard(canvas,mDroidCards,i);
  42.         }
  43.         drawLeftDroidCard(canvas,mDroidCards.get(mDroidCards.size() -1));
  44.         invalidate();
  45.     }

  46.     private void drawDroidCard(Canvas canvas,DroidCard card){
  47.         canvas.drawBitmap(card.bitmap,card.left,0f,paint);
  48.     }

  49.     private void drawLeftDroidCard(Canvas canvas,DroidCard card){
  50.         canvas.drawBitmap(card.bitmap,card.left,0f,paint);
  51.     }

  52.     private void drawDroidCard(Canvas canvas,List<DroidCard> list,int i){
  53.         DroidCard card = list.get(i);
  54.         /*Canvas中当前路径不属于保存状态,状态包含线条,平移,颜色,渐变,阴影等*/
  55.         canvas.save();//保存画布状态,第二次绘制在起点,因为这里每一个的x坐标是以左侧为起点累加的
  56.         //获取当前图片的 left 值,裁剪出当前图片显示的区域,并且绘制
  57.         canvas.clipRect(card.left,0f,list.get(i+1).left,card.height);
  58.         canvas.drawBitmap(card.bitmap,card.left,0f,paint);
  59.         canvas.restore();
  60.     }

  61. }
复制代码
  1. import android.content.res.Resources;
  2. import android.graphics.Bitmap;
  3. import android.graphics.BitmapFactory;

  4. public class DroidCard {

  5.     public Bitmap bitmap;
  6.     public int left,width,height;


  7.     public DroidCard(Resources resources,int resId,int left){
  8.         this.bitmap = BitmapFactory.decodeResource(resources,resId);
  9.         this.left = left;
  10.         this.width = bitmap.getWidth();
  11.         this.height = bitmap.getHeight();
  12.     }

  13. }
复制代码
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:tools="http://schemas.android.com/tools"
  5.     android:layout_width="match_parent"
  6.     android:layout_height="match_parent"
  7.     tools:context=".MainActivity">

  8.     <com.example.testdemo.DroidCardsView
  9.         android:layout_width="match_parent"
  10.         android:layout_height="150dp"
  11.         app:layout_constraintLeft_toLeftOf="parent"
  12.         app:layout_constraintTop_toTopOf="parent" />

  13. </RelativeLayout>
复制代码




新浪微博达人勋

注册会员

116

积分

36

威望

2

金钱

Rank: 2

积分
116
发表于 2019-5-21 14:30:44 | 显示全部楼层
前排顶,很好!

新浪微博达人勋

高级会员

1775

积分

592

威望

0

金钱

Rank: 6Rank: 6

积分
1775
发表于 2019-5-31 09:33:59 | 显示全部楼层
佩服佩服!

新浪微博达人勋

高级会员

822

积分

274

威望

0

金钱

Rank: 4

积分
822
发表于 5 天前 | 显示全部楼层
嘘,低调。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Archiver|手机版|小黑屋|安卓教程网 ( 粤ICP备12089784号  

GMT+8, 2019-6-16 14:53 , Processed in 0.593902 second(s), 50 queries .

Powered by Discuz X3.1

© 2001-2013 IOS教程网

快速回复 返回顶部 返回列表