首页 > 编程语言 >APP中RN页面渲染流程-ReactNative源码分析

APP中RN页面渲染流程-ReactNative源码分析

时间:2023-05-24 23:24:43浏览次数:61  
标签:原生 APP 视图 js 源码 组件 RN view

在APP启动后,RN框架开始启动。等RN框架启动后,就开始进行RN页面渲染了。 RN页面原生侧页面渲染的主要逻辑实现是在RCTUIManager和RCTShadowView完成的。 通过看UIMananger的源码可以看到,UIMananger导出给JS端的API接口在对UI的操作上,基本都会同时对 View 和 ShadowView 进行操作。 以更新视图为例:

RCTUIManager的作用 RCTUIManager的主要作用是负责管理React Native应用程序的视图的创建、更新和销毁;将原生组件注册到JS端;处理原生和React Native之间的通信; 具体如下: 1.视图的创建、更新和销毁。RCTUIManager负责创建并管理应用程序中的所有视图,包括文本、图像、按钮等。当需要更新或销毁视图时,RCTUIManager会负责处理相应的操作。 2.组件的注册。RCTUIManager负责注册应用程序中的所有组件,并提供相应的方法以便在React Native应用程序中使用。 3.原生和React Native之间的通信。RCTUIManager通过桥接层(Bridge)与原生平台进行通信,使得React Native应用程序可以在原生平台上运行和呈现UI界面。当React Native应用程序需要与原生平台进行交互时,RCTUIManager会负责处理相应的操作。   RCTShadowView的作用  RCTShadowView的主要作用是在APP中创建一棵YaGoNode节点树,用于记录视图的样式、布局、事件响应等信息,用于描述真实视图的属性和布局,从而提高渲染性能和效率。,它和UIView的关系类似于前端的虚拟DOM树和DOM树,两者是一一对应的关系。js对View的操作会先更新虚拟DOM,然后ReactNative在合适的时机批量更新到真实的View上。
RN页面的创建 在创建自定义RNView供js使用时,一般在创建一个RNView时,都要创建一个对应的RNViewManager用于管理Native与js的通讯。 UIMananger的创建在RN框架启动时,它在创建时会通过RCT_EXPORT_METHOD()宏将操作view的添加,修改,删除,调整层级等方法注入给js,供js操作原生view RN框架启动完成后则会进行RN页面渲染。   首先,js引擎执行rn代码,将rn中的组件转换成原生view展示到页面上。 js通过执行create代码,创建原生View

原生侧createView方法的主要执行步骤为:

RCT_EXPORT_METHOD(createView
: (nonnull NSNumber *)reactTag viewName
: (NSString *)viewName rootTag
: (nonnull NSNumber *)rootTag props
: (NSDictionary *)props)
1.根据模块名viewName从RCTBridge保存的全局变量中找到对应的模块信息 2.根据模块信息创建shadowview虚拟dom,保存到shadowView全局容器中 3.根据模块信息在主线程创建原生view,保存到view全局容器中   然后,执行setChildren:设置子视图 执行setChildren:设置子视图, 会将view添加到容器view的reactSubviews中(shadowView和UIView都是放到对应容器的reactSubviews属性中)[container insertReactSubview:view atIndex:index++];

原生侧setChildren方法的主要执行步骤为:

RCT_EXPORT_METHOD(setChildren : (nonnull NSNumber *)containerTag reactTags : (NSArray<NSNumber *> *)reactTags)
1.设置shadowView子视图,shadowView是设置到yoga树的叶子节点中:YGNodeInsertChild(_yogaNode, subview.yogaNode, (uint32_t)atIndex); 2.把设置view子视图任务添加到任务队列,[_pendingUIBlocks addObject:block];队列中的任务并不会立刻执行,而是等到合适的时机再执行。而当这个任务执行后,子View也并没有到真实的subviews中,而是放置到了reactSubviews关联属性中 objc_setAssociatedObject(self, @selector(reactSubviews), subviews, OBJC_ASSOCIATION_RETAIN_NONATOMIC);   _pendingUIBlocks队列执行时机 在js执行期间,js引擎通过Bridge桥接,把涉及到UI操作的事件按顺序封装成UIBlock放到Native原生侧的_pendingUIBlocks中,在等js代码执行完成后,原生模块会触发一个UIManager.batchDidComplete事件,表示js批量任务执行完成,开始刷新uiPending队列中的UI任务了。因此,在 JavaScript 执行完成前,RN 页面的 UI 并不会立即刷新。 方法调用顺序:batchDidComplete -> _layoutAndMount -> flushUIBlocksWithCompletion。 _pendingUIBlocks中的UIBlock执行后,最终会生成真实的原生view
- (void)didUpdateReactSubviews
{
  for (UIView *subview in self.reactSubviews) {
    [self addSubview:subview];
  }
}
 
  RN页面更新 当组件调用了setState属性更新时,通过updateView:刷新视图。 当出现插入、删除、排序组件时,通过manageChildren:更新视图。 updateView:刷新视图 当在RN中通过setState更改属性,js会对应生成一个新的虚拟DOM,通过diff算法,对应新旧DOM树生成修改点,然后通过updateView事件,将属性更新更新到原生侧的shadowView和View的_UIPendingQueue中。   当出现插入、删除、排序组件时,通过manageChildren:更新视图 containerTag:表示容器组件的标识符,即将在其中管理子组件。 moveFromIndices和moveToIndices:表示要移动的子组件的原始位置和目标位置的索引。 addChildReactTags和addAtIndices:表示要添加的子组件的标识符和它们在父容器中的位置索引。 removeAtIndices:表示要从父容器中删除的子组件的位置索引。 registry:表示React组件的注册表,其中包含所有已注册的组件及其实例。

 

       

标签:原生,APP,视图,js,源码,组件,RN,view
From: https://www.cnblogs.com/zhou--fei/p/17429837.html

相关文章

  • The Difficulty of Passive Learning in Deep Reinforcement Learning
    发表时间:2021(NeurIPS2021)文章要点:这篇文章提出一个tandemlearning的实验范式来研究为什么offlineRL很难学。对于offlineRL来说,一个很严重的问题就是extrapolationerror,也就是没见过的stateactionpair的估计是不准确的。再加上bootstrapping的更新方式,就会加剧误差导致o......
  • java基于springboot+vue的书籍学习平台管理系统,学期学习论坛管理系统,附源码+数据库+lw
    1、项目介绍困扰管理层的许多问题当中,书籍学习将会是不敢忽视的一块。但是管理好书籍学习又面临很多麻烦需要解决,在工作琐碎,记录繁多的情况下将书籍学习的当前情况反应给相关部门决策,等等。在此情况下开发一款书籍学习平台,于是乎变得非常合乎时宜。经过网上调查和搜集数据,......
  • HDFS文件因Hadoop版本原因导致append操作失败的问题
    问题重现:2023.05.24练习B站尚硅谷Hadoop3里的HDFS的Shell操作(append)[atguigu@hadoop102hadoop-3.3.4]$hadoopfs-appendToFileliubei.txt/sa点击查看代码[atguigu@hadoop102hadoop-3.3.4]$hadoopfs-appendToFileliubei.txt/sa2023-05-2420:30:37,303WARNhdfs.......
  • 《设计模式之禅》Singleton_Pattern--单例模式
    单例模式这个模式是很有意思,确实很有意思的,而且比较简单,但是我还是要说因为它使用的是如此的广泛,如此的有人缘,单例就是单一、独苗的意思,那什么是独一份呢?你的思维是独一份,除此之外还有什么不能山寨的呢?我们举个比较难复制的对象:皇帝(就是那个天子)中国的历史上很少出现两个皇帝并存的......
  • 常见问题解决 --- Failed to build android app at server - class file for android.
    问题原因  这个错误主要是LocalBroadcastManager这个类被弃用了,而在库或者sdk中使用到了。解决办法build.gradle文件中添加implementation'com.android.support:support-v4:30.4.1'gradle.properties添加android.enableJetifier=true......
  • springboot项目启动报错java.lang.NoSuchMethodError: org.springframework.boot.buil
    产生此问题的原因是由于springboot版本兼容性导致的:java.lang.NoSuchMethodError:org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V2019-08-2918:04:54.089ERROR[restartedMain][SpringApplication.java:842]-Applicationrunfail......
  • app里未读消息已读、未读是怎么设计的?
    也不知道大家目前都用的java编程软件有哪些,毕竟在应用程序中,未读和已读消息的设计取决于应用程序的需求和目标。下面是一些常见的设计模式:一、简单的未读/已读标记简单的未读/已读标记:这是最常见的设计,用户打开应用程序后,未读消息会用一个特殊的标记(通常是未读计数器)标识出来。当用......
  • A Knight's Journey
    [提交][状态]题目描述Theknightisgettingboredofseeingthesameblackandwhitesquaresagainandagainandhasdecidedtomakeajourneyaroundtheworld.Wheneveraknightmoves,itistwosquaresinonedirectionandonesquareperpendiculartoth......
  • 【IntelliJ IDEA】idea中的插件之一:Free Mybatis plugin跳转插件的使用(方便在Dao接口
    本文目录一、安装二、使用最近在使用一个非常好用的跳转插件,用着很顺手,效率比之前提高了很多。之前使用MyBatis框架或者是在IDEA中,发现Mapper接口和XML文件之间跳转十分的麻烦,我之前经常的操作是在Mapper接口中将接口名称复制一下,然后去查找对应的XML文件,打开后CRTL+F查找对应的xml......
  • 【异常】This application has no explicit mapping for /error, so you are seeing t
    本文目录一、错误提示二、错误原因2.1原因一:启动类的位置不对2.2原因二:控制器的URL路径书写问题 2.3原因三:配置文件中视图解析器的配置问题三、解决方案3.1解决方案一3.2解决方案二3.3解决方案三背景:使用springboot+vue构建的微信点餐系统一、错误提示最近在做一个项目,......