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

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

异步渲染(Asynchronous Rendering)

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

示例:

DispatchQueue.global(qos: .background).async {let processedImage = processImage(image)DispatchQueue.main.async {imageView.image = processedImage}
}

异步绘制(Asynchronous Drawing)

异步绘制则更专注于在后台线程进行实际的图形绘制操作,然后将绘制结果应用到 UI 上。这种做法不仅避免了主线程的阻塞,还能充分利用多线程的优势来提高图形绘制的效率和性能。

Core Graphics 和 Core Animation 是实现异步绘制的常用框架。例如,可以使用 CATiledLayer 来实现异步绘制大规模的图形。

示例:

class AsyncDrawingView: UIView {override class var layerClass: AnyClass {return CATiledLayer.self}override func draw(_ rect: CGRect) {let context = UIGraphicsGetCurrentContext()// 在此处执行绘制操作}
}let tiledLayer = AsyncDrawingView.layer as! CATiledLayer
tiledLayer.levelsOfDetail = 4
tiledLayer.levelsOfDetailBias = 3
tiledLayer.tileSize = CGSize(width: 256, height: 256)

区别与联系

  1. 目的和应用场景

    • 异步渲染主要用于将数据处理、图片加载等操作放在后台线程执行,然后在主线程更新 UI,以提高界面的响应速度。
    • 异步绘制主要用于在后台线程执行实际的图形绘制操作,以提高图形绘制的效率和性能。
  2. 实现方式

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

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


拓展

facebook Texture 的实现原理是基于异步渲染还是异步绘制 ?还是两个都有用到 ?

Facebook 的 Texture(以前称为 AsyncDisplayKit)框架主要基于异步绘制(Asynchronous Drawing)来提高用户界面的性能和响应速度,同时也涉及异步渲染(Asynchronous Rendering)的一些方面。Texture 通过将耗时的界面绘制和布局操作放在后台线程中执行,来避免阻塞主线程,从而提供流畅的用户体验。

Texture 实现原理

异步绘制(Asynchronous Drawing)

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

  1. ASDisplayNode

    • ASDisplayNode 是 Texture 的基本单元,类似于 UIView,但它支持异步绘制。
    • ASDisplayNode 在后台线程执行 drawRect: 方法,通过 Core Graphics 进行绘制,并生成一个包含绘制内容的图像。
  2. 异步绘制队列

    • Texture 使用专门的绘制队列来处理 ASDisplayNode 的绘制任务。绘制任务被分配到后台线程中执行,确保不会阻塞主线程。
  3. 绘制合成

    • 绘制完成后,生成的图像被合成到主线程的视图层次结构中,确保界面更新的流畅性。
异步渲染(Asynchronous Rendering)

除了异步绘制,Texture 也利用了异步渲染的概念,将一些耗时的布局和数据处理操作放在后台线程中执行,然后在主线程更新 UI。

  1. 异步布局

    • ASLayoutSpec 允许节点在后台线程进行布局计算。布局计算完成后,结果会被应用到主线程的界面中。
  2. 异步数据加载

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

结合使用

Texture 的强大之处在于它同时结合了异步绘制和异步渲染,通过将界面绘制、布局和数据加载等操作放在后台线程中执行,大大提高了界面的响应速度和流畅性。

以下是一个使用 Texture 的示例:

import AsyncDisplayKitclass AsyncImageNode: ASDisplayNode {let imageNode = ASImageNode()override init() {super.init()addSubnode(imageNode)}override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {return ASInsetLayoutSpec(insets: .zero, child: imageNode)}func setImage(_ image: UIImage?) {imageNode.image = image}
}let asyncImageNode = AsyncImageNode()
DispatchQueue.global().async {let image = loadImageFromNetwork()DispatchQueue.main.async {asyncImageNode.setImage(image)}
}

总结来说,Facebook 的 Texture 框架通过结合异步绘制和异步渲染,提供了强大的性能优化能力,使得复杂的界面操作可以在后台线程中高效执行,从而保证主线程的流畅性和用户体验。


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

iOS 开发中 UI 相关的操作不是要求必须在主线程么 ?为什么 Texture 可以把界面元素的渲染和布局操作移到后台线程 ?

在 iOS 开发中,确实有一个重要的原则:所有 UI 相关的操作必须在主线程上执行。这是因为 UIKit 不是线程安全的,多线程操作 UI 可能会导致不可预见的行为和崩溃。然而,Texture 框架通过巧妙的设计和实现,将界面元素的渲染和布局操作移到后台线程,而不违反这一原则。

Texture 如何实现异步渲染和布局

  1. 异步计算布局
    Texture 将布局计算移到后台线程。这些计算包括尺寸和位置的计算,而不是直接操作 UI。这意味着实际的 UI 更新还是在主线程上进行的,但计算工作已经在后台完成,从而减轻了主线程的负担。

    // Example of layout calculation in background thread
    [node measureWithSizeRange:ASSizeRangeMake(minSize, maxSize)];
    
  2. 异步绘制内容
    Texture 将绘制操作也移到了后台线程。具体来说,绘制操作会生成一个图像或其他内容,然后这些内容会在主线程上应用到 UI 组件中。这样,虽然绘制在后台完成,但实际的 UI 更新还是在主线程上进行的。

    self.imageNode.imageModificationBlock = ^UIImage *(UIImage *image) {// Perform image modifications in background threadUIGraphicsBeginImageContextWithOptions(image.size, NO, [[UIScreen mainScreen] scale]);[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];UIImage *modifiedImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return modifiedImage;
    };
    
  3. 双缓冲技术(Double Buffering)
    Texture 使用双缓冲技术来确保 UI 更新的线程安全。后台线程进行布局和绘制后,生成的内容会被传递给主线程,主线程只负责最终的 UI 更新。这种方法确保了 UI 操作在主线程上进行,同时最大限度地利用了后台线程的计算能力。

    [ASDisplayNode performBlockOnMainThread:^{// Apply the result of the background rendering to the UI[self.layer setContents:(__bridge id _Nullable)(image.CGImage)];
    }];
    
  4. 节点(Node)系统
    Texture 的核心概念是节点(Node)系统,每个节点都是一个独立的实体,负责其自己的布局和渲染。节点的布局计算和绘制操作可以在后台线程中进行,而最终的 UI 更新还是在主线程上完成。

    ASDisplayNode *node = [[ASDisplayNode alloc] init];
    node.backgroundColor = [UIColor redColor];
    node.frame = CGRectMake(0, 0, 100, 100);
    

小结

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


拓展 - Texture 的异步绘制操作

Texture 将绘制操作移到后台线程,具体是怎么实现的 ?

Texture 框架通过几个关键机制将绘制操作移到后台线程,并确保这些操作最终在主线程上应用,以保持线程安全。以下是 Texture 实现异步绘制的具体步骤和原理:

1. 异步绘制任务分配

Texture 使用 ASDisplayNode 进行异步绘制任务的分配。每个 ASDisplayNode 都有一个 display 方法,该方法负责节点的绘制。Texture 会在后台线程中执行这个方法。

ASDisplayNode *node = [[ASDisplayNode alloc] init];
node.displayBlock = ^UIImage * {// 这是在后台线程中执行的绘制操作UIGraphicsBeginImageContextWithOptions(size, NO, 0);CGContextRef context = UIGraphicsGetCurrentContext();// 在 context 上执行绘制操作// ...UIImage *image = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return image;
};

2. 使用异步绘制队列

Texture 维护了一个全局的异步绘制队列 ASDisplayQueue,它负责管理所有节点的异步绘制任务。每个绘制任务都会被放到这个队列中执行。

ASDisplayQueue *displayQueue = [ASDisplayQueue sharedDisplayQueue];
[displayQueue addDisplayBlock:^{// 执行节点的 displayBlockUIImage *image = node.displayBlock();// 在主线程上应用绘制结果dispatch_async(dispatch_get_main_queue(), ^{node.contents = (id)image.CGImage;});
}];

3. 双缓冲机制

为了确保主线程的 UI 更新是线程安全的,Texture 使用了双缓冲机制。在后台线程完成绘制操作后,绘制的结果(通常是 UIImage)会被缓冲,然后在主线程上应用到相应的 CALayer

- (void)displayAsync:(BOOL)asynchronously {if (asynchronously) {dispatch_async(_asyncDisplayQueue, ^{UIImage *image = [self displayBlock]();dispatch_async(dispatch_get_main_queue(), ^{self.layer.contents = (id)image.CGImage;});});} else {UIImage *image = [self displayBlock]();self.layer.contents = (id)image.CGImage;}
}

4. 高效的图层绘制

Texture 使用 CATiledLayer 来处理大规模图形的异步绘制。CATiledLayer 会将图形分成若干小块,每块都可以在后台线程中独立绘制。这种方式不仅提高了绘制效率,还减少了内存占用。

CATiledLayer *tiledLayer = [CATiledLayer layer];
tiledLayer.tileSize = CGSizeMake(256, 256);
tiledLayer.levelsOfDetail = 4;
tiledLayer.levelsOfDetailBias = 3;

5. 异步图像加载

Texture 提供了 ASNetworkImageNode 来异步加载和显示网络图像。图像下载和处理在后台线程中进行,完成后在主线程上更新 UI。

ASNetworkImageNode *imageNode = [[ASNetworkImageNode alloc] init];
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 上。

示例:异步绘制图像
ASDisplayNode *node = [[ASDisplayNode alloc] init];
node.displayBlock = ^UIImage * {// 在后台线程中执行绘制操作CGSize size = CGSizeMake(100, 100);UIGraphicsBeginImageContextWithOptions(size, NO, 0);CGContextRef context = UIGraphicsGetCurrentContext();// 使用 Core Graphics 绘制内容CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);CGContextFillRect(context, CGRectMake(0, 0, 100, 100));UIImage *image = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return image;
};

在这个例子中,displayBlock 在后台线程中执行,使用 Core Graphics 在 UIGraphicsGetCurrentContext() 上进行绘制操作。生成的 UIImage 最终会在主线程上应用到节点的内容中。

Core Animation

Core Animation 是一个强大的动画和图层绘制框架,Texture 使用 Core Animation 来管理和优化图层的显示,特别是在处理大规模图形和复杂动画时。CATiledLayer 是 Core Animation 中一个重要的类,Texture 使用它来实现异步绘制大规模图形。

示例:使用 CATiledLayer 实现异步绘制
class AsyncDrawingView: UIView {override class var layerClass: AnyClass {return CATiledLayer.self}override func draw(_ rect: CGRect) {let context = UIGraphicsGetCurrentContext()// 在此处执行绘制操作CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);CGContextFillRect(context, rect);}
}let tiledLayer = AsyncDrawingView.layer as! CATiledLayer
tiledLayer.levelsOfDetail = 4
tiledLayer.levelsOfDetailBias = 3
tiledLayer.tileSize = CGSize(width: 256, height: 256)

在这个例子中,CATiledLayer 将视图的内容分成多个小块,并在后台线程中独立绘制这些小块。这种方式不仅提高了绘制效率,还减少了内存占用。

Texture 的异步绘制流程

  1. 定义节点和绘制块
    每个 ASDisplayNode 可以定义一个 displayBlock,该块在后台线程中执行,使用 Core Graphics 进行绘制操作。

  2. 后台线程绘制
    Texture 使用 ASDisplayQueue 将绘制任务分配到后台线程执行。在这些任务中,使用 Core Graphics 进行实际的绘制操作。

  3. 主线程应用绘制结果
    在后台线程完成绘制操作后,生成的 UIImage 或其他内容会被传递到主线程,并应用到节点的 CALayer 中。

  4. 使用 CATiledLayer 优化大规模绘制
    对于需要处理大规模图形的场景,Texture 使用 CATiledLayer 将绘制任务分成小块,并在后台线程中并行绘制这些小块。

小结

Texture 框架在实现异步绘制时,主要使用 Core Graphics 来处理后台线程中的绘制操作,并结合 Core Animation(特别是 CATiledLayer)来优化图层显示和管理。这种结合使得 Texture 能够提供高性能的异步渲染和绘制能力,同时保持 UIKit 的线程安全原则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SVN的使用- SVN的基本命令-SVN命令简写-注意事项-解决冲突 Objective-C语言】

一、SVN的更新命令:update 1.服务器如果新建了一个文件夹,yuanxing,版本变成6了, 我现在本地还只有三个文件夹,版本5, 终端里边,我们敲一个svn update, 我这儿就多了一个yuanxing文件夹, 这个就是更新,就是把服务器最新的代码下载下来, 假设服务器上大家提交了这…

react VS vue

什么是react 用于构建用户界面的js库 什么是vue 用于构建用户界面的渐进式js库 react是基于mvvm设计还是mvc设计 1、react是基于mvc设计的,但也不是完整的mvc模式 2、react把自己定义为view 3、组件逻辑定义为Controller层 4、虽然react不是完整的mvc模式&a…

KNIME 5.2.5 版本界面切换

1、安装完KNIME后,点击“Create workflow in your local space.” 2、发现是这个样子 4、进行切换。点击“menu”,最后点击“Switch to classic user interfaceto” 5、最终显示结果:

补光灯LED照明 2.7V4.2V5V升60V80V100V升压恒流芯片IC-H6902B

H6902B升压恒流芯片IC确实是一款为LED照明应用设计的稳定且可靠的解决方案。这款芯片具有以下几个显著特点: 高效率:效率高达95%以上,这意味着在驱动LED灯时,电源到LED的能量转换效率非常高,减少了能量损失&#xff0…

代码随想录算法训练营:30/60

非科班学习算法day30 | LeetCode452:用最少数量的箭引爆气球 ,Leetcode435:无重叠区间 ,Leetcode763:划分字母区间 介绍 包含LC的两道题目,还有相应概念的补充。 相关图解和更多版本: 代码随想录 (programmercarl.com)https:/…

centos磁盘空间满了-问题解决

报错问题解释: CentOS系统在运行过程中可能会出现磁盘空间不足的错误。这通常发生在以下几种情况: 系统日志文件或临时文件过大导致磁盘空间不足。 安装了大量软件或文件而没有清理无用文件。 有可能是某个进程占用了大量磁盘空间。 问题解决方法&a…

多服务下,服务与服务之间的调用(SpringCloudAlibaba入门一)

多服务下,服务与服务之间的调用(SpringCloudAlibaba入门一) 说明直接看代码 说明 在SpringBoot情况下,如果我们有多个子模块而且代码之间没有相互引用,那么子项目与子项目之间的调用方式就只能通过http请求的方式去调用…

必看!微信小程序必备证书!

微信小程序必备SSL证书。在日益增长的数字经济中,微信小程序已成为商家与消费者之间重要的交互平台。由于其便捷性和广泛的用户基础,越来越多的企业选择通过小程序来提供服务。然而,在开发和部署微信小程序时,确保数据安全是一个不…

Ubuntu22.04.4 LTS系统/安装Anaconda【GPU版】

安装过程 1.wget命令行下载 下载Anaconda并保存文件至本地指定目录 wget -c https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh -P ~/Downloads/anaconda3 查看是否下载好了 2.安装Anaconda 2.1 bash命令安装 bash后面是anaconda3下载好的路径 bash …

学生选课管理系统(Java+MySQL)

技术栈 Java: 用于实现系统的核心业务逻辑。MySQL: 作为关系型数据库,用于存储系统中的数据。JDBC: 用于Java程序与MySQL数据库之间的连接和交互。Swing GUI: 用于创建图形用户界面,提升用户体验。 系统功能 我们的学生选课管理系统主要针对学生和管理…

AIGC 与软件开发:是助力还是取代?

《AIGC 与软件开发:是助力还是取代?》 在当今的软件开发领域,生成式人工智能(AIGC)的崛起无疑是一场变革性的浪潮。从代码生成到错误检测,再到自动化测试,AI 工具正以前所未有的方式融入开发者…

vue3源码(六)渲染原理-runtime-core

1.依赖关系 runtime-dom 依赖于runtime-core,runtime-core 依赖于reactivity和sharedruntime-core提供跨平台的渲染方法createRenderer,用户可以自己传递节点渲染的渲染方法renderOptions,本身不关心用户使用什么APIruntime-dom提供了为浏览器而生的渲染…

MSI打包后门成安装包

目录 浏览器下载地址 启动>next 选择后门所在路径,和生成安装包后存放路径 next>Hidden 配置变量 Look up随便找个伪装,然后点击一下Creat New ​注册表Registry导入 ​点击否,不购买专业版 ​安装包生成成功​编辑 浏览器下…

Mybatis进阶の常用配置级联查询

2 Mybatis常用配置 mybatis-config.xml中除了可以配置数据库服务器的环境以外,还可以配置其他的操作,帮助开发人员简化配置代码。常见的配置信息有以下内容: 1 配置内容 SqlMapConfig.xml中配置的内容和顺序如下:properties&am…

(自用)共享单车服务器(一):服务器项目配置

项目目录结构 conf:用来存放配置文件 git:用来存放从git上克隆的项目 src:用来存放项目源文件 test:用来存放测试文件 third:用来存放第三方头文件、第三方库 安装iniparser(关于iniparser的使用需进一步学习) 1.项目目录中创建git文件夹,用于存放GitHub上克隆…

计算机网络-IGMPv1工作原理简介

一、IGMPv1的原理简介 前面我们大致了解了IGMP用于在连接组播组成员的组播路由器总通过交互IGMP报文生成IGMP组表项和IGMP路由表项。IGMP报文封装在IP报文中。到目前为止,IGMP有三个版本:IGMPv1、IGMPv2、IGMPv3。 今天主要学习IGMPv1的作用和工作原理。…

深度学习论文: LLaMA: Open and Efficient Foundation Language Models

深度学习论文: LLaMA: Open and Efficient Foundation Language Models LLaMA: Open and Efficient Foundation Language Models PDF:https://arxiv.org/pdf/2302.13971.pdf PyTorch: https://github.com/shanglianlm0525/PyTorch-Networks 1 概述 本文介绍了LLaMA&#xff0…

浅谈重要组件JSR223介绍

浅谈重要组件JSR223介绍 JSR223 脚本组件是一个极其强大的特性,它允许用户利用各种脚本语言编写复杂的测试逻辑,极大地增强了 JMeter 的灵活性和功能。本文将对 JSR223 进行详细介绍,并解释如何在 JMeter 测试计划中有效地应用它。 JSR223 …

数据开源 | Magic Data大模型高质量十万轮对话数据集

能够自然的与人类进行聊天交谈,是现今的大语言模型 (LLM) 区别于传统语言模型的重要能力之一,近日OpenAI推出的GPT-4o给我们展示了这样的可能性。 对话于人类来说是与生俱来的,但构建具备对话能力的大模型是一项不小的挑战,收集高…

基于Android平台开发,仿头条新闻app

1. 项目模块功能思维导图 2. 项目涉及到的技术点 数据来源:聚合数据API使用okhttp网络请求框架获取api数据使用gson库解析json数据使用RecyclerViewadapter实现新闻列表使用SQLite数据库实现用户登录,注册,浏览历史记录使用SharedPreference…