Commit Transaction 由上面的流程我们可以看到,在开发中我们可以影响到的主要就是 Handle Events 和 Commit Transaction 这两个阶段,一般我们做优化和调试也是在这两个阶段。Handle Events 就是处理触摸事件,而 Commit Transaction 这部分中主要进行的是:Layout、Display、Prepare、Commit 等四个具体的操作。
1. Layout:构建视图
这个阶段主要处理视图的构建和布局,具体步骤包括:
调用重载的 layoutSubviews
方法 创建视图,并通过 addSubview
方法添加子视图 计算视图布局,即所有的 Layout Constraint 由于这个阶段是在 CPU 中进行,通常是 CPU 限制或者 IO 限制,所以我们应该尽量高效轻量地操作,减少这部分的时间,比如减少非必要的视图创建、简化布局计算、减少视图层级等。
2. Display:绘制视图
这个阶段主要是交给 Core Graphics 进行视图的绘制,注意不是真正的显示,而是得到图元 primitives
数据,通常是三角形、线段、顶点等:
根据上一阶段 Layout 的结果创建得到图元信息。 如果重写了 drawRect:
方法,那么会调用重载的 drawRect:
方法,在 drawRect:
方法中手动绘制得到 bitmap 数据,从而自定义视图的绘制。 注意正常情况下 Display 阶段只会得到图元 primitives
信息,而位图 bitmap 是在 GPU 中根据图元信息绘制得到的。但是如果重写了 drawRect:
方法,这个方法会直接调用 Core Graphics 绘制方法得到 bitmap 数据,同时系统会额外申请一块内存,用于暂存绘制好的 bitmap。
由于重写了 drawRect:
方法,导致绘制过程从 GPU 转移到了 CPU,这就导致了一定的效率损失。与此同时,这个过程会额外使用 CPU 和内存,因此需要高效绘制,否则容易造成 CPU 卡顿或者内存爆炸。
3. Prepare:Core Animation 额外的工作
这一步主要是:图片解码和转换。
4. Commit:打包并发送
这一步主要是:图层打包并发送到 Render Server。
注意 commit 操作是依赖图层树递归执行的,所以如果图层树过于复杂,commit 的开销就会很大。这也是我们希望减少视图层级,从而降低图层树复杂度的原因。