Android 绘制知识点总结

Android 绘制知识点总结

Android绘制流程

  • 绘制前世今生

    我们都知道,当一个Activity调用setContenView之后,我们就可以看到我们的内容被展示出来,那么到底是谁,将我们的页面内容,转变成屏幕显示的像素数据呢,我们从来一步步分析

  • DecorView是我们应用窗口的一个根容器,SetContentView,其实就是将内容防止到DecorView的子元素idContentView的容器中

  • Window窗口,每一个窗口有一个和它关联的Surface,窗口的SurfaceWMS分配,画在表面上的内容并不会马上显示在屏幕上,绘制完成之后,SurfaceFlinger将多块Surface按照顺序(Z-order)进行混合,输出到FrameBuff,显示到界面

    SurfaceView就是有一个单独Surface

  • Window具体实现为PhoneWindow,和Activity唯一对应,PhoneWindow中持有DecorView,Activity.setContentView的操作就是通过PhoneWindow来完成

    Activity,Window,View的三者关系,Activity工匠,Window窗户,View窗花

  • ViewRoot,实现类ViewRootImple,会在ActivityThread.handleResumeActivity()DecorView进行关联,而后会调用requestLayout发起绘制

  • 绘制的起点,ViewRootImpl.requestLayout ->scheduleTraversals() -> performTraversals()

    • measure -> 计算出每个控件需要占据的尺寸
      • MeasureSpec,32整数,SpecMode2位+SpecSize 剩余30位,
        • 测量模式
          • EXACTLY 精准模式,指定了具体的尺寸,如12dp,或者是match_parent
          • AT_MOST,最大模式,不得超过SpecSize
          • UNSPECIFIED,未定义,不做限制,类似ListView这种系统内部控件
    • layout->计算出每个控件的绘制位置
    • draw -> 每个空间的具体绘制内容
  • 绘制核心SurfaceFlinger

    • 无论是OpenGL ES还是Canvas,获取MediaPlayer等生产者产生的图像数据都会输出到Surface,

    • Surface也是作为SurfaceFlinger的生产者,将GraphicBuffer通过IPC传到SurfaceFlinger,

    • 最终 SurfaceFlinger根据WMS提供的窗口信息,合成所有的Layer

      (Layer和Surface相关联,SurfaceLayer的屏幕内存的直接表现)

    • 图形绘制,不同的方式,都是输出到Surface
      • Canvas
        • Sika软件绘制
        • hwui硬件加速绘制
      • OpenGL ES
    • BufferQueue,在之前的生产者-消费者模式中,所有的数据传输都是通过BufferQueue
      • Canvas/OpenGLES请求一块空闲的缓存区填充图像数据dequeueBuffer(),然后将数据返回给队列: queueBuffer()
      • SurfaceFlinger合成所有图层数据,放到输出缓存区
      • Display显示控制器 获取合成结果 acquireBuffer(),使用完毕,则返回给队列: releaseBuffer()
  • 双缓冲

    CPU计算好显示内容之后,GPU负责渲染到FrameBuffer帧缓冲,然后按照VSync信用从帧缓冲中取出数据显示到屏幕上,如果只有一块缓冲区,那么数据的更新可能就是表现为逐行的刷新,为了刷新是整帧的,需要双缓冲,刷新时进行直接替换

Android硬件加速

Android中,硬件加速,就是将View的绘制工作交给GPU来完成,Android4.0以后,硬件加速都是默认开启的

Android硬件加速踩坑

  • 一些Android 4.0的低端机型,出现花屏,黑色像素,错位等现象,错误日志OpenGLRender:0x510

    • 针对一些自定义的复杂的View,可能会存在渲染异常,出现这种情况,可以优先考虑关闭硬件加速

      • Application级别关闭,慎用,这可能会让你整个应用的渲染性能下降

         
        
      • Activity级别关闭,悠着点,影响也不小

        
        
      • Window级别,悠着点,也是和Activity类似

        getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        
      • View级别,这个比较推荐!!

        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//指定为软件渲染
        //也可以在布局文件xml中
        android:layerType="software"
        
  • 针对一些绘制相关的操作,也有一些api是在特定版本后才开始支持硬件加速的

    • Api 支持版本
      canvas.clipRegion() 18
      canvas.clipPath() 18

      Android官方文档列出的所有Api支持情况

大佬相关博客原文地址

  • Android图形系统概述
  • Android图形系统概述
  • Android 绘制原理浅析

你可能感兴趣的:(Android 绘制知识点总结)