异步绘制原理

UI绘制的过程

UI绘制原理的过程.png

当调用[UIView setNeedsDisplay]方法时,系统会立即调用对应的layer的setNeedsDisplay,之后给layer打上标记,在一次RunLoop将要结束时,会调用[CALayer display]方法,然后进入到真正的绘制过程当中。

[CALayer display]方法内部实现中,会判断有没有layer的delegate响应了displayLayer方法,如果没有会执行系统绘制流程,如果响应了就为我们提供了异步绘制的入口。

系统绘制流程

在CALayer内部会创建一个backing store(CGContextRef),然后layer会判断它是否有代理,如果没有代理的话,会调用[CALayer drawInContext:], 如果有代理,会调用[layer.delegate drawLayer: inContext],然后做当前视图的绘制工作,这部分是发生在系统内部的,然后在一个合适的时机给予我们一个回调方法,就是[UIView drawRect:][UIView drawRect:]的默认实现是什么都不做,给我们开一个口子,就允许我们在系统绘制的基础上做一些其他的相关的绘制工作,最后不论是哪个分支,都是由CALayer上传对应的backing store(可以理解为位图)到GPU

异步绘制

[layer.delegate drawLayer:inContext:]方法实现就可以进入到异步绘制的流程

  • 代理负责生产对应的bitmap
  • 设置该bitmap作为layer.contents属性的值

异步绘制的机制和流程

异步绘制的机制和流程.png

在调用setNeedsDisplay方法之后,在当前RunLoop快要结束时,由系统调用视图所对应的CALayer的display方法,然后如果代理实现了displayLayer:函数,会调用代理的displayLayer:函数方法,然后会通过子线程的切换,在子线程中做位图的绘制,此时主线程可以做别的事。

在全局并发队列子线程中

  1. 通过CGBitmapContextCreate()函数来创建一个位图的上下文
  2. 通过CoreGraphics的相关api做当前UI空间的绘制工作
  3. 再通过CGBitmapContextCreateImage()函数来根据当前所绘制的上下文,生成一张CGImage图片
  4. 然后回到主队列中提交位图,设置给CALayer的contents属性,这样就完成了一个UI控件的异步绘制

来自 https://leejnull.github.io/2020/03/09/2020-03-09-01/

你可能感兴趣的:(异步绘制原理)