- 原文做者: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