iOS 异步渲染

279 阅读2分钟

异步渲染(Asynchronous Rendering)

异步渲染主要指在后台线程(子线程)进行与界面显示相关的耗时操作,比如图片加载、文本排版、数据处理等,然后在主线程更新 UI。这种做法的主要目的是避免阻塞主线程,降低主线程的压力,以确保用户界面的流畅性和响应速度。

异步渲染通常使用 GCD 或 OperationQueue 进行后台线程的任务分发。

一 UIView绘制渲染原理和流程

image.png

  1. UIView调用setNeedsDisplay(setNeedsDisplay会调用自动调用drawRect方法);
  2. 系统会立刻调用view的layer的同名方法[view.layer setNeedsDisplay],之后相当于在layer上面打上了一个刷新标记;
  3. 然后再当前runloop将要结束的时候,才会调用CALayer的display函数方法,然后才进入到当前视图的真正绘制工作的流程当中;
  4. runloop即将结束, 开始视图的绘制流程;
系统默认绘制流程

image.png

  1. CALayer内部创建一个backing store(CGContextRef)();
  2. 判断layer是否有代理(1.有代理:调用delegete的drawLayer:inContext, 然后在合适的 实际回调代理, 在[UIView drawRect]中做一些绘制工作;2. 没有代理:调用layer的drawInContext方法。)
  3. layer上传backingStore到GPU, 结束系统的绘制流程;
异步绘制流程

image.png

  1. 某个时机调用setNeedsDisplay;
  2. runloop将要结束的时候调用[CALayer display]
  3. 如果代理实现了dispalyLayer将会调用此方法, 在子线程中去做异步绘制的工作;
  4. 子线程中做的工作:创建上下文, 控件的绘制, 生成图片;
  5. 转到主线程, 设置layer.contents, 将生成的视图展示在layer上面;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
        ///获取当前上下文
        UIGraphicsBeginImageContextWithOptions(size, false, scale);
        //1.获取上下文
        UIGraphicsGetCurrentContext();
        //TODO
         ...............
        //生成图片
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        ///子线程完成工作, 切换到主线程展示
        dispatch_async(dispatch_get_main_queue(), ^{
            self.layer.contents = img;
        })
    });

第三方: YYKit

Graver