- 原文做者:Mehul Mohan
- 原文连接: How React Native constructs app layouts (and how Fabric is about to change it)
- 做者 React Native 入门教程:React Native - First Steps
- 做者 Twitter: Mehul Mohan
- 介绍视频 The future of React Native - RN Fabric (is pretty awesome!)
React Native
团队一直致力研究一些能够从根本上改变 React Native
内部与操做系统协同工做的方式。 在官方没发布前,暂且称它们这个项目为 “Project Fabric”吧。 让咱们一块儿来讨论下它是什么以及它将会为开发人员带来怎样的变化。javascript
React Native
目前使用3个线程:java
UI线程 - 这是运行 Android / iOS
应用程序的主要应用程序线程。 它能够访问UI,UI也只能由此线程更改。react
影子线程 - 此线程是 React Native
用于计算 React
建立的布局的后台线程。android
JavaScript线程 - 此线程是 JavaScript
代码(其实是您的 React
代码)的执行环境。git
让咱们来从头开始分析下它的构建过程,假设你要在屏幕中央绘制一个红色框。 那么,你的JS线程将包含用于建立这个布局的代码。 如下一段典型的 React Native(RN) 布局代码:github
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<View style={{width: 100, height: 100, backgroundColor: "red"}}></View>
</View>
复制代码
系统有本身的布局实现方式,它并不理解你刚刚编写的 Flexbox
代码。所以,RN
首先必须将您的 Flexbox
编码布局转换为系统能够理解的布局系统。编程
继续来看,在转换以前,咱们须要将此布局计算部分转交到另外一个线程,以便咱们能够保持 JavaScript
线程继续执行。所以,RN使用了影子线程,它本质上是在构建了JS线程中编码的布局树。在这个线程中,RN 使用了一个名为 Yoga 的布局引擎,它将基于 Flexbox
的布局将其转换为系统能够理解的布局。react-native
React Native
使用 React Native bridge
将这些信息从JS线程传递给Shadow线程。 简而言之,这只是以JSON格式序列化数据并将其做为字符串传输到 React Native bridge
上。浏览器
这时,咱们正处于Shadow线程中。JS线程正在执行,屏幕上没有任何内容。 一旦咱们从 yoga
得到了渲染标记,这些信息将再次经过 React Native bridge
传输到UI线程。 一样,这会在Shadow线程上执行一些序列化并在主线程上执行反序列化。而后主线程会渲染出 UI。多线程
你能够看到,线程之间的全部通讯都发生在 bridge
上,可是同时存在不少限制。 包括:
另外,全部的通讯都是异步的,在大多数状况下这是没问题的。 可是,目前没有办法同步从JS线程更新UI线程。当您使用具备大量数据的 FlatList
时,这就会产生问题。(你能够将 FlatList
视为 RecyclerView
的较差实现。) 最后,因为JS线程和UI线程之间通讯是这种异步的方式,严格要求同步数据访问的原生模块并不能彻底使用。 例如,android
上的 RecyclerView
为了屏幕上没有闪烁,适配器须要同步访问它所呈现的数据。 因为目前 React Native
的多线程架构,没法作到这一点。
咱们回头来看看浏览器的布局。咱们仔细想下,浏览器渲染出的输入框,按钮等其实是依赖于操做系统的。所以,在渲染时,你的浏览器会询问您的操做系统(Windows,Mac,Linux或其余的系统),例如,应该在网页上的哪一个位置绘制输入框?那让咱们来看下浏览器和React Native
的线程映射关系。
UI线程 → UI线程
浏览器渲染引擎 → React Native渲染引擎(Yoga / Shadow thread)
JavaScript线程 → JavaScript线程
咱们知道现代浏览器很是成熟,能够有效地处理掉全部这些任务。 那为何 React Native
不能这么作呢?是什么限制了它不能像浏览器这样来工做呢?
你曾经有没有在控制台中写过像 document.getElementById
这样的命令以及 setTimeout
和 setInterval
之类的代码并看到打印出的结果?他们的实现结果是 [native code]
, 这是什么意思呢?能够发现,当你执行这些方法时,它们不会调用任何 JavaScript
代码。反而,这些方法会直接调用到本机的C ++代码。因此其实浏览器不容许JS使用桥接与主机操做系统进行通讯,而是使用本机代码直接向系统暴露JS接口!简而言之,这就是 React Native Fabric
将要作的事情:消除桥接通讯而且使用本机代码直接经过JS线程控制UI。
图片来源:https://www.slideshare.net/axemclion/react-native-fabric-review20180725