【译】React Native布局原理(以及Fabric将作出的改变)

React Native 团队一直致力研究一些能够从根本上改变 React Native内部与操做系统协同工做的方式。 在官方没发布前,暂且称它们这个项目为 “Project Fabric”吧。 让咱们一块儿来讨论下它是什么以及它将会为开发人员带来怎样的变化。javascript

目前React Native是如何工做的

React Native 目前使用3个线程:java

  1. UI线程 - 这是运行 Android / iOS 应用程序的主要应用程序线程。 它能够访问UI,UI也只能由此线程更改。react

  2. 影子线程 - 此线程是 React Native 用于计算 React 建立的布局的后台线程。android

  3. 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 上,可是同时存在不少限制。 包括:

  • 传输较大数据(好比将图像转换为base64字符串信息)会很慢, 若是只需指向内存中的数据就能够实现相同的任务,这些就是没必要要的数据拷贝

另外,全部的通讯都是异步的,在大多数状况下这是没问题的。 可是,目前没有办法同步从JS线程更新UI线程。当您使用具备大量数据的 FlatList 时,这就会产生问题。(你能够将 FlatList 视为 RecyclerView 的较差实现。) 最后,因为JS线程和UI线程之间通讯是这种异步的方式,严格要求同步数据访问的原生模块并不能彻底使用。 例如,android 上的 RecyclerView 为了屏幕上没有闪烁,适配器须要同步访问它所呈现的数据。 因为目前 React Native 的多线程架构,没法作到这一点。

介绍Fabric

咱们回头来看看浏览器的布局。咱们仔细想下,浏览器渲染出的输入框,按钮等其实是依赖于操做系统的。所以,在渲染时,你的浏览器会询问您的操做系统(Windows,Mac,Linux或其余的系统),例如,应该在网页上的哪一个位置绘制输入框?那让咱们来看下浏览器和React Native 的线程映射关系。

  • UI线程 → UI线程

  • 浏览器渲染引擎 → React Native渲染引擎(Yoga / Shadow thread)

  • JavaScript线程 → JavaScript线程

咱们知道现代浏览器很是成熟,能够有效地处理掉全部这些任务。 那为何 React Native不能这么作呢?是什么限制了它不能像浏览器这样来工做呢?

将Native API直接暴露给JavaScript

你曾经有没有在控制台中写过像 document.getElementById 这样的命令以及 setTimeoutsetInterval 之类的代码并看到打印出的结果?他们的实现结果是 [native code] , 这是什么意思呢?能够发现,当你执行这些方法时,它们不会调用任何 JavaScript 代码。反而,这些方法会直接调用到本机的C ++代码。因此其实浏览器不容许JS使用桥接与主机操做系统进行通讯,而是使用本机代码直接向系统暴露JS接口!简而言之,这就是 React Native Fabric 将要作的事情:消除桥接通讯而且使用本机代码直接经过JS线程控制UI。

其它

  • RN Fabric 容许 UI 线程(绘制UI的位置)与JS线程(UI编程的位置)同步
  • Fabric 仍处于开发阶段,React Native 团队确实没有提到截至目前的公开发布日期。 但我很肯定今年咱们会看到一些很棒的东西。
  • 像这样的应用程序开发框架(RN,NativeScript,Flutter)将会发展的愈来愈好!

图片来源:https://www.slideshare.net/axemclion/react-native-fabric-review20180725

相关文章
相关标签/搜索