iOS 开辟中,异步渲染和异步绘制

打印 上一主题 下一主题

主题 783|帖子 783|积分 2359

在 iOS 开辟中,异步渲染(Asynchronous Rendering)和异步绘制(Asynchronous Drawing)固然有相似之处,但它们并不是完全雷同的概念。
异步渲染(Asynchronous Rendering)

异步渲染主要指在背景线程进行与界面体现相关的耗时操作,比如图片加载、文本排版、数据处置惩罚等,然后在主线程更新 UI。这种做法的主要目标是避免壅闭主线程,以确保用户界面的流通性和响应速度。
示例:
  1. DispatchQueue.global(qos: .background).async {
  2.     let processedImage = processImage(image)
  3.     DispatchQueue.main.async {
  4.         imageView.image = processedImage
  5.     }
  6. }
复制代码
异步绘制(Asynchronous Drawing)

异步绘制则更专注于在背景线程进行实际的图形绘制操作,然后将绘制结果应用到 UI 上。这种做法不仅避免了主线程的壅闭,还能充分利用多线程的优势来提高图形绘制的服从和性能。
Core Graphics 和 Core Animation 是实现异步绘制的常用框架。比方,可以利用 CATiledLayer 来实现异步绘制大规模的图形。
示例:
  1. class AsyncDrawingView: UIView {
  2.     override class var layerClass: AnyClass {
  3.         return CATiledLayer.self
  4.     }
  5.     override func draw(_ rect: CGRect) {
  6.         let context = UIGraphicsGetCurrentContext()
  7.         // 在此处执行绘制操作
  8.     }
  9. }
  10. let tiledLayer = AsyncDrawingView.layer as! CATiledLayer
  11. tiledLayer.levelsOfDetail = 4
  12. tiledLayer.levelsOfDetailBias = 3
  13. tiledLayer.tileSize = CGSize(width: 256, height: 256)
复制代码
区别与接洽


  • 目标和应用场景

    • 异步渲染主要用于将数据处置惩罚、图片加载等操作放在背景线程实验,然后在主线程更新 UI,以提高界面的响应速度。
    • 异步绘制主要用于在背景线程实验实际的图形绘制操作,以提高图形绘制的服从和性能。

  • 实现方式

    • 异步渲染通常利用 GCD 或 OperationQueue 进行背景线程的任务分发。
    • 异步绘制通常利用 Core Graphics 或 Core Animation 等图形框架,并利用专门的图层(如 CATiledLayer)来进行背景绘制。

总结来说,异步渲染和异步绘制在概念和实现上有一些交叉,但它们的偏重点和应用场景有所不同。异步渲染更多地涉及数据处置惩罚和界面更新,而异步绘制则专注于高效的图形绘制操作。

拓展

   facebook Texture 的实现原理是基于异步渲染照旧异步绘制 ?照旧两个都有用到 ?
  Facebook 的 Texture(从前称为 AsyncDisplayKit)框架主要基于异步绘制(Asynchronous Drawing)来提高用户界面的性能和响应速度,同时也涉及异步渲染(Asynchronous Rendering)的一些方面。Texture 通过将耗时的界面绘制和结构操作放在背景线程中实验,来避免壅闭主线程,从而提供流通的用户体验。
Texture 实现原理

异步绘制(Asynchronous Drawing)

Texture 的核心功能之一是异步绘制。它通过在背景线程进行实际的图形绘制操作,然后将绘制结果合成到主线程上体现。这一过程主要通过以下机制实现:

  • ASDisplayNode

    • ASDisplayNode 是 Texture 的根本单元,雷同于 UIView,但它支持异步绘制。
    • ASDisplayNode 在背景线程实验 drawRect: 方法,通过 Core Graphics 进行绘制,并天生一个包罗绘制内容的图像。

  • 异步绘制队列

    • Texture 利用专门的绘制队列来处置惩罚 ASDisplayNode 的绘制任务。绘制任务被分配到背景线程中实验,确保不会壅闭主线程。

  • 绘制合成

    • 绘制完成后,天生的图像被合成到主线程的视图层次结构中,确保界面更新的流通性。

异步渲染(Asynchronous Rendering)

除了异步绘制,Texture 也利用了异步渲染的概念,将一些耗时的结构和数据处置惩罚操作放在背景线程中实验,然后在主线程更新 UI。

  • 异步结构

    • ASLayoutSpec 允许节点在背景线程进行结构计算。结构计算完成后,结果会被应用到主线程的界面中。

  • 异步数据加载

    • Texture 支持在背景线程加载数据,如图片和文本内容,然后将结果异步应用到 UI 组件上。

联合利用

Texture 的强大之处在于它同时联合了异步绘制和异步渲染,通过将界面绘制、结构和数据加载等操作放在背景线程中实验,大大提高了界面的响应速度和流通性。
以下是一个利用 Texture 的示例:
  1. import AsyncDisplayKit
  2. class AsyncImageNode: ASDisplayNode {
  3.     let imageNode = ASImageNode()
  4.     override init() {
  5.         super.init()
  6.         addSubnode(imageNode)
  7.     }
  8.     override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  9.         return ASInsetLayoutSpec(insets: .zero, child: imageNode)
  10.     }
  11.     func setImage(_ image: UIImage?) {
  12.         imageNode.image = image
  13.     }
  14. }
  15. let asyncImageNode = AsyncImageNode()
  16. DispatchQueue.global().async {
  17.     let image = loadImageFromNetwork()
  18.     DispatchQueue.main.async {
  19.         asyncImageNode.setImage(image)
  20.     }
  21. }
复制代码
总结来说,Facebook 的 Texture 框架通过联合异步绘制和异步渲染,提供了强大的性能优化能力,使得复杂的界面操作可以在背景线程中高效实验,从而保证主线程的流通性和用户体验。

拓展 - 主线程操作UI的疑问

   iOS 开辟中 UI 相关的操作不是要求必须在主线程么 ?为什么 Texture 可以把界面元素的渲染和结构操作移到背景线程 ?
  在 iOS 开辟中,确实有一个紧张的原则:所有 UI 相关的操作必须在主线程上实验。这是因为 UIKit 不是线程安全的,多线程操作 UI 可能会导致不可预见的行为和崩溃。然而,Texture 框架通过奇妙的设计和实现,将界面元素的渲染和结构操作移到背景线程,而不违背这一原则。
Texture 怎样实现异步渲染和结构


  • 异步计算结构
    Texture 将结构计算移到背景线程。这些计算包括尺寸和位置的计算,而不是直接操作 UI。这意味着实际的 UI 更新照旧在主线程上进行的,但计算工作已经在背景完成,从而减轻了主线程的负担。
    1. // Example of layout calculation in background thread
    2. [node measureWithSizeRange:ASSizeRangeMake(minSize, maxSize)];
    复制代码
  • 异步绘制内容
    Texture 将绘制操作也移到了背景线程。具体来说,绘制操作会天生一个图像或其他内容,然后这些内容会在主线程上应用到 UI 组件中。如许,固然绘制在背景完成,但实际的 UI 更新照旧在主线程上进行的。
    1. self.imageNode.imageModificationBlock = ^UIImage *(UIImage *image) {
    2.     // Perform image modifications in background thread
    3.     UIGraphicsBeginImageContextWithOptions(image.size, NO, [[UIScreen mainScreen] scale]);
    4.     [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    5.     UIImage *modifiedImage = UIGraphicsGetImageFromCurrentImageContext();
    6.     UIGraphicsEndImageContext();
    7.     return modifiedImage;
    8. };
    复制代码
  • 双缓冲技能(Double Buffering)
    Texture 利用双缓冲技能来确保 UI 更新的线程安全。背景线程进行结构和绘制后,天生的内容会被传递给主线程,主线程只负责最终的 UI 更新。这种方法确保了 UI 操作在主线程上进行,同时最大限度地利用了背景线程的计算能力。
    1. [ASDisplayNode performBlockOnMainThread:^{
    2.     // Apply the result of the background rendering to the UI
    3.     [self.layer setContents:(__bridge id _Nullable)(image.CGImage)];
    4. }];
    复制代码
  • 节点(Node)系统
    Texture 的核心概念是节点(Node)系统,每个节点都是一个独立的实体,负责其自己的结构和渲染。节点的结构计算和绘制操作可以在背景线程中进行,而最终的 UI 更新照旧在主线程上完成。
    1. ASDisplayNode *node = [[ASDisplayNode alloc] init];
    2. node.backgroundColor = [UIColor redColor];
    3. node.frame = CGRectMake(0, 0, 100, 100);
    复制代码
小结

Texture 通过将结构计算和绘制操作移到背景线程来提高性能,但它始终确保最终的 UI 更新在主线程上进行,从而遵守 iOS 的 UI 线程安全原则。通过这种方式,Texture 可以大概实现异步渲染和结构,从而提高应用的响应速度和性能,而不违背 UIKit 的线程安全要求。

拓展 - Texture 的异步绘制操作

   Texture 将绘制操作移到背景线程,具体是怎么实现的 ?
  Texture 框架通过几个关键机制将绘制操作移到背景线程,并确保这些操作最终在主线程上应用,以保持线程安全。以下是 Texture 实现异步绘制的具体步调和原理:
1. 异步绘制任务分配

Texture 利用 ASDisplayNode 进行异步绘制任务的分配。每个 ASDisplayNode 都有一个 display 方法,该方法负责节点的绘制。Texture 会在背景线程中实验这个方法。
  1. ASDisplayNode *node = [[ASDisplayNode alloc] init];
  2. node.displayBlock = ^UIImage * {
  3.     // 这是在后台线程中执行的绘制操作
  4.     UIGraphicsBeginImageContextWithOptions(size, NO, 0);
  5.     CGContextRef context = UIGraphicsGetCurrentContext();
  6.    
  7.     // 在 context 上执行绘制操作
  8.     // ...
  9.    
  10.     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  11.     UIGraphicsEndImageContext();
  12.    
  13.     return image;
  14. };
复制代码
2. 利用异步绘制队列

Texture 维护了一个全局的异步绘制队列 ASDisplayQueue,它负责管理所有节点的异步绘制任务。每个绘制任务都会被放到这个队列中实验。
  1. ASDisplayQueue *displayQueue = [ASDisplayQueue sharedDisplayQueue];
  2. [displayQueue addDisplayBlock:^{
  3.     // 执行节点的 displayBlock
  4.     UIImage *image = node.displayBlock();
  5.    
  6.     // 在主线程上应用绘制结果
  7.     dispatch_async(dispatch_get_main_queue(), ^{
  8.         node.contents = (id)image.CGImage;
  9.     });
  10. }];
复制代码
3. 双缓冲机制

为了确保主线程的 UI 更新是线程安全的,Texture 利用了双缓冲机制。在背景线程完成绘制操作后,绘制的结果(通常是 UIImage)会被缓冲,然后在主线程上应用到相应的 CALayer。
  1. - (void)displayAsync:(BOOL)asynchronously {
  2.     if (asynchronously) {
  3.         dispatch_async(_asyncDisplayQueue, ^{
  4.             UIImage *image = [self displayBlock]();
  5.             dispatch_async(dispatch_get_main_queue(), ^{
  6.                 self.layer.contents = (id)image.CGImage;
  7.             });
  8.         });
  9.     } else {
  10.         UIImage *image = [self displayBlock]();
  11.         self.layer.contents = (id)image.CGImage;
  12.     }
  13. }
复制代码
4. 高效的图层绘制

Texture 利用 CATiledLayer 来处置惩罚大规模图形的异步绘制。CATiledLayer 会将图形分成若干小块,每块都可以在背景线程中独立绘制。这种方式不仅提高了绘礼服从,还淘汰了内存占用。
  1. CATiledLayer *tiledLayer = [CATiledLayer layer];
  2. tiledLayer.tileSize = CGSizeMake(256, 256);
  3. tiledLayer.levelsOfDetail = 4;
  4. tiledLayer.levelsOfDetailBias = 3;
复制代码
5. 异步图像加载

Texture 提供了 ASNetworkImageNode 来异步加载和体现网络图像。图像下载和处置惩罚在背景线程中进行,完成后在主线程上更新 UI。
  1. ASNetworkImageNode *imageNode = [[ASNetworkImageNode alloc] init];
  2. imageNode.URL = [NSURL URLWithString:@"https://example.com/image.jpg"];
复制代码
小结

Texture 框架通过将绘制操作分配到背景线程实验,并利用双缓冲机制和 CATiledLayer 等技能,确保异步绘制的结果可以大概安全、高效地应用到主线程的 UI 上。这些技能使得 Texture 可以大概提供高性能的异步渲染和绘制能力,同时保持 UIKit 的线程安全原则。

拓展 - 具体用到的框架

   Texture 将绘制操作分配到背景线程实验,利用的是 Core Graphics 照旧 Core Animation ?
  Texture 框架主要利用 Core Graphics 和 Core Animation 来实现异步绘制操作。以下是它们在 Texture 中的具体应用方式:
Core Graphics

Core Graphics 是一个强大的二维图形绘制框架,Texture 利用 Core Graphics 来处置惩罚背景线程中的绘制操作。这包括天生图像、绘制文本、绘制图形等。Core Graphics 允许在背景线程中实验这些绘制操作,然后将天生的图像应用到 UI 上。
示例:异步绘制图像

  1. ASDisplayNode *node = [[ASDisplayNode alloc] init];
  2. node.displayBlock = ^UIImage * {
  3.     // 在后台线程中执行绘制操作
  4.     CGSize size = CGSizeMake(100, 100);
  5.     UIGraphicsBeginImageContextWithOptions(size, NO, 0);
  6.     CGContextRef context = UIGraphicsGetCurrentContext();
  7.    
  8.     // 使用 Core Graphics 绘制内容
  9.     CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
  10.     CGContextFillRect(context, CGRectMake(0, 0, 100, 100));
  11.    
  12.     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  13.     UIGraphicsEndImageContext();
  14.    
  15.     return image;
  16. };
复制代码
在这个例子中,displayBlock 在背景线程中实验,利用 Core Graphics 在 UIGraphicsGetCurrentContext() 上进行绘制操作。天生的 UIImage 最终会在主线程上应用到节点的内容中。
Core Animation

Core Animation 是一个强大的动画和图层绘制框架,Texture 利用 Core Animation 来管理和优化图层的体现,特殊是在处置惩罚大规模图形和复杂动画时。CATiledLayer 是 Core Animation 中一个紧张的类,Texture 利用它来实现异步绘制大规模图形。
示例:利用 CATiledLayer 实现异步绘制

  1. class AsyncDrawingView: UIView {
  2.     override class var layerClass: AnyClass {
  3.         return CATiledLayer.self
  4.     }
  5.     override func draw(_ rect: CGRect) {
  6.         let context = UIGraphicsGetCurrentContext()
  7.         // 在此处执行绘制操作
  8.         CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
  9.         CGContextFillRect(context, rect);
  10.     }
  11. }
  12. let tiledLayer = AsyncDrawingView.layer as! CATiledLayer
  13. tiledLayer.levelsOfDetail = 4
  14. tiledLayer.levelsOfDetailBias = 3
  15. tiledLayer.tileSize = CGSize(width: 256, height: 256)
复制代码
在这个例子中,CATiledLayer 将视图的内容分成多个小块,并在背景线程中独立绘制这些小块。这种方式不仅提高了绘礼服从,还淘汰了内存占用。
Texture 的异步绘制流程


  • 定义节点和绘制块
    每个 ASDisplayNode 可以定义一个 displayBlock,该块在背景线程中实验,利用 Core Graphics 进行绘制操作。
  • 背景线程绘制
    Texture 利用 ASDisplayQueue 将绘制任务分配到背景线程实验。在这些任务中,利用 Core Graphics 进行实际的绘制操作。
  • 主线程应用绘制结果
    在背景线程完成绘制操作后,天生的 UIImage 或其他内容会被传递到主线程,并应用到节点的 CALayer 中。
  • 利用 CATiledLayer 优化大规模绘制
    对于必要处置惩罚大规模图形的场景,Texture 利用 CATiledLayer 将绘制任务分成小块,并在背景线程中并行绘制这些小块。
小结

Texture 框架在实现异步绘制时,主要利用 Core Graphics 来处置惩罚背景线程中的绘制操作,并联合 Core Animation(特殊是 CATiledLayer)来优化图层体现和管理。这种联合使得 Texture 可以大概提供高性能的异步渲染和绘制能力,同时保持 UIKit 的线程安全原则。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表