Texture的简介 (What)node
为何要使用Texture (Why)git
Texture的做者 (Who)github
Node的异步绘制如何实现 (How)缓存
Node的异步渲染(Runloop任务分发)如何实现 (How)数据结构
Texture的布局引擎 (How)架构
Texture的使用能带来什么收益 (How Much)并发
texture简介:框架
Texture(原名AsyncDisplayKit)是FaceBook开源的一款可以保持界面流畅的框架。创建在UIKit之上,能够保持最复杂的用户界面的流畅和响应。(smooth and responsive)异步
Texture总体架构oop
Node:对UIView和CALayer的抽象
Node Containers:node容器,负责加载渲染node
Layout Engineer:node布局
Texture节点容器与UIKit
Texture节点子类与UIKit
Texture节点子类继承树
为何要使用Texture
布局计算、解码、绘制,异步并发执行
Runloop任务分发(异步渲染)
声明式布局系统
图层预合成
深度优化列表性能(智能预加载)
Texture:图层预合成
有时一个 layer 会包含不少 sub-layer,而这些 sub-layer 并不须要响应触摸事件,也不须要进行动画和位置调整。ASDK 为此实现了一个被称为 pre-composing 的技术,能够把这些 sub-layer 合成渲染为一张图片。开发时,ASNode 已经替代了 UIView 和 CALayer;直接使用各类 Node 控件并设置为 layer backed 后,ASNode 甚至能够经过预合成来避免建立内部的 UIView 和 CALayer。
经过这种方式,把一个大的层级,经过一个大的绘制方法绘制到一张图上,性能会得到很大提高。CPU 避免了建立 UIKit 对象的资源消耗,GPU 避免了多张 texture 合成和渲染的消耗,更少的 bitmap 也意味着更少的内存占用。
图层预合成
Texture:智能预加载
全部节点都持有当前界面状态interfaceState,由ASRangeController控制属性值更新,在全部节点容器的内部建立和维护。
智能预加载
Preload:节点还不可见,这时节点收集外部源(API或磁盘数据)
Display:节点开始渲染,包括文本的光栅化以及图像解码等
Visible:节点可见,在屏幕上至少拥有一个像素
Texture的做者
Scott Goodson
ASDK 的做者是 Scott Goodson ,他曾经在苹果工做,负责 iOS 的一些内置应用的开发,好比股票、计算器、地图、钟表、设置、Safari 等,固然他也参与了 UIKit framework 的开发。后来他加入 Facebook 后,负责 Paper 的开发,建立并开源了 AsyncDisplayKit。目前他在 Pinterest 和 Instagram 负责 iOS 开发和用户体验的提高等工做。
Node的异步绘制如何实现
UIKit的绘制机制图解
CALayer的display方法由系统调用,用来更新layer的内容,若是layer有delegate对象,那么display方法将尝试调用delegate的displayLayer:方法来更新layer的内容。若是delegate没有实现displayLayer:方法,则这个方法会建立一个backing store来保存原来的内容,而后调用layer的drawInContext:方法来填充back store。最后以新的backing store替换layer的先前内容达到更新layer的目的。一般UIKit中CALayer的delegate是UIView对象。
有两种方式来自定义CALayer的内容,一种是直接设置CALayer的contents属性来建立寄宿图;另外一种是经过实现CALayer的delegate方法,能够用于直接对CALayer进行操做。
Node的异步绘制
UIKit
Texture
ASDisplayNode是整个Texture的基石,也是页面异步绘制的核心,其持有UIView和CALayer两种对象,均由node本身生成并管理。
异步绘制时序图
_ASDisplayLayer经过重写了CALayer的display方法来自定义CALayer的寄宿图属性。_ASDisplayLayer与ASDisplayNode的关系相似于CALayer与UIView的关系。
Node的异步绘制流程
获取node的displayBlock,也就是负责根据node的视图层级获得须要显示的内容的绘制任务。
生成Node绘制完成后的回调completeBlock。
根据displaysAsynchronously属性来判断是否须要异步绘制,若是是异步的,则将displayBlock提交至_ASAsyncTransaction中,不然当即执行displayBlock。
Node的异步渲染
寻找Layer相关的ASAsyncTransaction。
将displayBlock和completeBlock添加至ASAsyncTransaction。
利用ASAsyncTransactionQueue进行调度。
mainRunloop在开始sleep和exit的时候提交ASAsyncTransaction。
ASAsyncTransaction在提交的时候回调completeBlock,完成layer寄宿图的赋值。
<ps:displayblock执行不在主线程,completeblock执行在主线程!>
底层信号驱动原理
iOS的显示系统由VSync信号驱动的,VSync信号由硬件时钟生成,每秒钟发出60次。iOS图形服务接收到VSync信号后,会经过IPC通知到APP内。APP的Runloop在启动后会注册对应CFRunloopSource经过mach_port接收传过来的时钟信号通知,随后source的回调会驱动整个App的动画与显示。
Runloop任务分发 ->CoreAnimation
CA在Runloop中注册了一个Observer,监听了BeforeWaiting和Exit事件,优先级低于其余Observer。当一个触摸事件到来时,Runloop被唤醒,App中的代码会执行一些操做,好比建立和调整视图层级、设置UIView的frame、修改CALayer的透明度、为视图添加一个动画;这些操做最终会被CALayer捕获,并经过CATransaction提交到一个中间状态去。当上面的全部操做结束后,Runloop即将进入休眠(或者退出)时,关注该事件的Observer都会获得通知。这时CA注册的Observer就会在回调中,把全部的中间状态合并提交到GPU去显示;若是此处有动画,CA会经过CADisplayLink等机制屡次触发相关流程。
Runloop任务分发->Texture
Texture在此处模拟了Core Animation的这个机制:全部针对ASNode的修改和提交,总有些任务是必须放入主线程执行的。当出现这种任务时,ASNode会把任务用ASAsyncTransaction(Group)封装并提交到一个全局的容器去。Texture也在Runloop中注册了一个Observer,监视的事件和CA同样,但优先级比CA要低。当Runloop进入休眠前、CA处理完事件后,Texture就会执行该loop内提交的全部任务。经过这种机制,Texture能够在合适的机会把异步、并发的操做同步到主线程去,而且能得到不错的性能。
Texture布局引擎
相对于AutoLayout
UIKit AutoLayout 在复杂的视图结构中,计算量会呈指数级增加,Texture的布局方案相对AutoLayout有如下优势:
快:Texture的布局计算和手写frame同样快
异步和并发:布局能够在后台线程上计算
声明式渲染:布局使用不可变的数据结构声明,实现一个layout视角从专一view之间的距离和约束,转变成划分和制定不一样view子域的布局规则,抽象层级变高,使得布局代码更容易开发、维护
可缓存:若是布局是不变的,自动在后台预先计算并缓存
可拓展:在不一样的类中使用相同的布局会变得很方便
Texture的布局系统
Texture本身定义了一套强大的automatic layout布局系统,这套布局系统基于CSS的Box Model,经过提出LayoutSpec概念,使得咱们能够经过声明式的方法来定义布局。
layoutTable
:一种特殊的layoutTable,与node不一样的是,它本质只是内存中的数据结构,用以辅助view的位置计算,绘制时不须要view来占位或者承载子元素。
布局系统
Texture布局规则&布局元素
布局规则:充当LayoutElements的容器,经过多个LayoutElements之间的关联,完成LayoutElements的位置排列,继承自ASLayoutSpec。
布局元素:全部的ASDisplayNode和ASLayoutSpec都遵照协议,能够经过两个Nodes和其余的LayoutSpecs,生成或者组合一个新的LayoutSpecs。协议及LayoutSpecs有一些属性用于建立很是复杂的布局。
Texture布局流程图
Texture布局示例
Texture布局调试
在任何ASDisplayNode或ASLayoutSpec上调用-asciiArtString都会返回该对象及其子项的字符图,也能够设置.debugName这样也会包含在字符图中。
还能够在任何ASLayoutElement,好比Node和LayoutSpec上打印样式对象,调试.size属性。
声明式布局Demo连接:
https://ysw-hello@github.com/ysw-hello/TextureLayoutDemo.git
Texture所能带来的收益
异步绘制、异步渲染经过Runloop任务分发,优化复杂界面的主线程卡顿现象。
图层预合成、智能预加载的机制,对列表进行深度优化,使得体验与性能获得进一步的提高。
声明式布局方式,FlexBox布局特色,给iOS原生开发的布局模式带来一种新的布局思惟,很新颖,颇有特色。