启动流程

React Native启动流程

现在,每当启动React Native应用程序时,要加载的第一个项目是本机入口点。Native线程产生JS VM线程,该线程运行捆绑的JS代码。JS代码具有应用程序的所有业务逻辑。JS基础设施初始化.主要是require等基本模块的加载并替换JS默认的实现。自定义require, Warning window, Alert window, fetch等都是在这里进行的。基础设施初始化好以后就可以开始加载js代码了。

Native线程现在通过RN Bridge发送消息以启动JS应用程序。现在,生成的Javascript线程开始通过RN Bridge向本机线程发出指令。说明包括要加载的视图,要从硬件检索的信息等。例如,如果JS线程想要创建视图和文本,它将把请求批处理为单个消息并将其发送到 用于渲染它们的本机线程。

[ [2,3,[2,'Text',{...}]] [2,3,[3,'View',{...

本机线程将执行这些操作并将结果发送回JS,以确保已执行操作。

image.png

原生代码初始化

这里讨论的主要是RN相关的原生代码和用户自定义的RN模块的原生代码的加载和初始化。原生代码初始化主要分两步:

  • 静态加载。iOS没有动态加载原生代码的接口,所有的代码都在编译的初期就已经编译为静态代码并且链接好,程序启动的时候所有的原生代码都会加载好。这是原生代码的静态加载,iOS里面没有动态加载原生代码的概念,这也是为何没有静态代码热更新的原因。

  • RN模块解析和注入JS。这是加载的第二步。在RootView初始化的时候会遍历所有被标记为RCTModule的原生模块,生成一个json格式的模块信息,里面包含模块名称和方法名称,然后注入到JS Engine,MessageQueue记录下来。原生代码在生成json模块信息的时候同时会在原生代码这边维护一个名称字典,用来把模块和方法的名称映射到原生代码的地址上去,用于JS调用原生代码的翻译。

Javascript环境初始化

RN的初始化是从RCRootView开始的,所有的绘制都会在这个RootView里面进行(Alert除外).RootView做的第一件事情就是初始化一个空的JS Engine。这个空的JS Engine里面包含一些最基础的模块和方法(fetch, require, alert),没有UI绘制模块。RN的工作就是替换这些基础的模块和方法,然后把RNUI绘制模块加载并注入到JS EngineJS Engine不直接管理UI的绘制。

  • 所有的绘制由原生控制的UI事件和Timer触发
  • 影响界面刷新的事件发生以后一部分直接由原生控件消化掉,直接更新原生控件。剩下的部分会通过Bridge派发给MessageQueue,然后在JS层进行业务逻辑的计算,再由React来进行Virtual Dom的管理和更新。Virtual Dom再通过MessageQueue发送重绘指令给对应的原生组件进行UI更新。

Native Modules加载

OC里面,所有NativeModules要加载进JS Engine都必须遵循一定的协议(protocol)

模块(OC里面的类)需要声明为,然后在类里面还必须调用宏RCT_EXPORT_MODULE()用来定义一个接口告诉JS当前模块叫什么名字。这个宏可以接受一个可选的参数,指定模块名,不指定的情况下就取类名。

对应的JS模块在初始化的时候会调用原生类的[xxx new]方法.

模块声明为后只是告诉Native Modules这有一个原生模块,是一个空的模块。要导出任何方法给JS使用都必须手动用宏RCT_EXPORT_METHOD来导出方法给JS.

所有的原生模块都会注册到NativeModules这一个JS模块下面去,你如果想要让自己的模块成为一个顶级模块就必须再写一个JS文件封装一遍NativeModules里面的方法。

你如果想自己的方法导出就默认成为顶级方法,那么你需要一个手动去调用JSC的接口,这个在前面章节有讲解。不建议这样做,因为这样你会失去跨JS引擎的便利性。

你可以导出常量到JS里面去,模块初始化的时候会坚持用户是否有实现constantsToExport方法,接受一个常量词典。

- (NSDictionary *)constantsToExport
{
  return @{ @"firstDayOfTheWeek": @"Monday" };// JS里面可以直接调用 ModuleName.firstDayOfTheWeek获取这个常量
}

常量只会在初始化的时候调用一次,动态修改该方法的返回值无效

所有标记为RCT_EXPORT_MODULE的模块都会在程序启动的时候自动注册好这些模块,主要是记录模块名和方法名。只是注册,不一定会初始化。

懒加载的模块

React NativeNativeModules是有延迟加载机制的。App初始化的时候

React Native JS接口兼容(Polyfills) fetch替换 CommonJS Require alert替换 console.warning替换 console.error替换

上一页
下一页