【譯】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

相關文章
相關標籤/搜索