
- 原文作者: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”吧。
讓我們一起來討論下它是什麼以及它將會為開發人員帶來怎樣的變化。
目前React Native是如何工作的
React Native
目前使用3個執行緒:

-
UI執行緒 - 這是執行
Android / iOS
應用程式的主要應用程式執行緒。 它可以訪問UI,UI也只能由此執行緒更改。 -
影子執行緒 - 此執行緒是
React Native
用於計算React
建立的佈局的後臺執行緒。 -
JavaScript執行緒 - 此執行緒是
JavaScript
程式碼(實際上是您的React
程式碼)的執行環境。
內部通訊
讓我們來從頭開始分析下它的構建過程,假設你要在螢幕中央繪製一個紅色框。 那麼,你的JS執行緒將包含用於建立這個佈局的程式碼。 以下一段典型的 React Native(RN) 佈局程式碼:
<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 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
這樣的命令以及 setTimeout
和 setInterval
之類的程式碼並看到列印出的結果?他們的實現結果是 [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