ReactNative啟動流程

ReactNative 的實現(xiàn)原理是什么?

ReactNative 的本質是在 JS 端編寫 React 代碼圆凰,通過 JavaScriptCore 引擎杈帐,把 JS 端編寫的組件和事件轉換成 Native 原生組件進行渲染。所以理解 ReactNative 的實現(xiàn)原理专钉,主要是搞清楚 JS 端與 Native 端的通信原理挑童。

要保證 JavaScript 和 Native 具備向對方通信的能力,首先需要搞清楚 RN 在啟動的時候都做了些啥跃须,這篇文章就是基于 ReactNatve 源碼分析的基礎上站叼,對 ReactNative 的啟動流程進行深入淺出的分析。

概述

  • ReactNative 啟動是從創(chuàng)建一個 RCTRootView 作為入口視圖容器開始運作的菇民,創(chuàng)建 RCTRootView 時尽楔,會先創(chuàng)建一個 JSBridge 作為 Native 端與 JS 端交互的橋梁。整個 RN 的啟動工作基本都是在創(chuàng)建 JSBridge 時做的玉雾。

  • JSBridge 的核心是 RCTBatchedBridge 的,JSBridge 的工作主要在 RCTBatchedBridge 初始化中處理轻要。啟動流程采用 GCD 來進行多線程操作复旬,其中大部分耗時操作是在并發(fā)隊列com.facebook.react.RCTBridgeQueue中進行的。

  • RCTBatchedBridge 啟動主要進行六個準備工作:

1.加載 JSBundle 代碼(并行隊列異步執(zhí)行)
2.初始化 Native Modules(同步執(zhí)行)
3.初始化 JSCExecutor(與第4步在同一并行隊列同時執(zhí)行)
4.創(chuàng)建 Module 配置表(與第3步在同一并行隊列同時執(zhí)行)
5.注入 Module 配置信息到 JSCExecutor(第3冲泥、4步執(zhí)行完再執(zhí)行)
6.執(zhí)行 JSBundle 代碼(前5步都執(zhí)行完再執(zhí)行)
rn啟動流程圖

1.加載 JSBundle 代碼

JSBundle: React代碼經(jīng)過打包后生成的JavaScript 源碼和圖片等資源文件

熱更新實質:將JSBundle放在服務器驹碍,在合適時機(啟動/切換前后臺/打開某個頁面按需加載等)壁涎,將JSBundle下載到本地來實現(xiàn)熱更新

將 JavaScript 源碼加載到內存中,方便之后注入和執(zhí)行志秃,這一步中怔球,React 中的 JSX 語法已經(jīng)轉換成 JavaScript。執(zhí)行代碼如下:

[RCTBatchedBridge loadSource: onProgress:]

2.初始化 Native Modules

同步初始化所有不能被懶惰加載的供 JS 端調用的 Native 模塊浮还。

Native Modules: 所有Native需要暴露給 JS 的類(即標有宏:RCT_EXPORT_MODULE()的類)

主要作用:找到所有 Native 需要暴露給 JavaScript 的類(即被標記有宏:RCT_EXPORT_MODULE()的類)竟坛,方便后面把這些模塊信息注入 JS 端。執(zhí)行代碼如下:

[RCTBatchedBridge initModulesWithDispatchGroup:]

3.初始化 JSCExecutor

JSCExecutor:JavaScriptCore引擎钧舌,負責JS端和Native端的通信

執(zhí)行代碼如下:

[RCTBatchedBridge setUpExecutor]

1.初始化時担汤,創(chuàng)建一個優(yōu)先級跟主線程優(yōu)先級同級的單獨的 JS 線程,同時創(chuàng)建一個 Runloop洼冻,讓 JS 線程能循環(huán)執(zhí)行不會退出崭歧。

2.初始化時,通過 JavaScriptCore 作為引擎撞牢,創(chuàng)建 JS 執(zhí)行的上下文環(huán)境率碾,并向 JS 上下文中注入 JS 與 Native 通信的方法。其中屋彪,在 Native 端實現(xiàn)的供 JS 端調用的幾個重要方法:

  • nativeRequireModuleConfig :js 獲取 native module 配置表所宰。RN 并沒有保存整個的 Native 方法配置表,而僅僅保存了模塊的名字撼班。這個回調就是 JS 每次根據(jù) module 名可以查到這個 module 的模塊配置信息

  • nativeFlushQueueImmediate: js 觸發(fā) native 進行隊列消息處理歧匈。一般來說 JS 并不會主動調用 Native 的方法,而是等著 Native 定時器每隔一段時間到 JS 的 eventQueue 中去取砰嘁,取出來以后批量執(zhí)行件炉。而 nativeFlushQueueImmediate 就是讓 JS 直接調用 Native 的方法而不用等待。

  • nativeCallSyncHook:同步調用

4.創(chuàng)建 Module 配置表

Module 配置表:
1.把所有模塊信息集中收集起來矮湘,保存到一個數(shù)組中斟冕,經(jīng)過序列化后,注入到JS中缅阳。

2.JS 端通過 Native 端注入的 nativeRequireModuleConfig 方法磕蛇,根據(jù) module 名可以查詢該模塊配置信息。

創(chuàng)建 Module 配置表十办,與初始化 JSCExecutor 的操作一起被加入并發(fā)隊列com.facebook.react.RCTBridgeQueue異步進行秀撇。執(zhí)行代碼如下:

[RCTBatchedBridge moduleConfig]
- (NSString *)moduleConfig
{
  NSMutableArray<NSArray *> *config = [NSMutableArray new];
  for (RCTModuleData *moduleData in _moduleDataByID) {
    if (self.executorClass == [RCTJSCExecutor class]) {
      [config addObject:@[moduleData.name]];
    } else {
      [config addObject:RCTNullIfNil(moduleData.config)];
    }
  }

  return RCTJSONStringify(@{
    @"remoteModuleConfig": config,
  }, NULL);
}

獲取 moduleConfig 時,會根據(jù)設置不同的 executorClass向族,收集的模塊信息會有區(qū)別呵燕,如果是RCTJSCExecutor類型,Native 端只保存模塊的名字件相,JS 端通過 Native 端注入的nativeRequireModuleConfig方法再扭,根據(jù) module 名可以查到這個 module 的模塊配置信息氧苍。如果不是RCTJSCExecutor類型,通過moduleData.config 鏈接到[RCTModuleData config]泛范,會把 module 名让虐、常量、函數(shù)等 native module 的配置信息都保存起來罢荡。

5.注入 Module 配置信息到 JS 端

執(zhí)行 [RCTBatchedBridge injectJSONConfiguration:onComplete:]

當 初始化 JSCExecutor 和 創(chuàng)建 Module 配置表 都準備好后赡突,會將 module 的模塊配置信息注入 JS 端。

6.執(zhí)行 JSBundle 代碼

執(zhí)行 [RCTBatchedBridge executeSourceCode:]

以上五步操作都執(zhí)行完成后柠傍,執(zhí)行 JSBundle 中的 JavaScript 源碼麸俘。至此,JavaScript 和 Objective-C 都具備了向對方交互的能力惧笛,啟動流程的準備工作算是全部完成了从媚。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市患整,隨后出現(xiàn)的幾起案子拜效,更是在濱河造成了極大的恐慌,老刑警劉巖各谚,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紧憾,死亡現(xiàn)場離奇詭異,居然都是意外死亡昌渤,警方通過查閱死者的電腦和手機赴穗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膀息,“玉大人般眉,你說我怎么就攤上這事∏敝В” “怎么了甸赃?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長冗酿。 經(jīng)常有香客問我埠对,道長,這世上最難降的妖魔是什么裁替? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任项玛,我火速辦了婚禮,結果婚禮上弱判,老公的妹妹穿的比我還像新娘襟沮。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布臣嚣。 她就那樣靜靜地躺著,像睡著了一般剥哑。 火紅的嫁衣襯著肌膚如雪硅则。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天株婴,我揣著相機與錄音怎虫,去河邊找鬼。 笑死困介,一個胖子當著我的面吹牛大审,可吹牛的內容都是我干的。 我是一名探鬼主播座哩,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼徒扶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了根穷?” 一聲冷哼從身側響起姜骡,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屿良,沒想到半個月后圈澈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡尘惧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年康栈,在試婚紗的時候發(fā)現(xiàn)自己被綠了矢炼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盏求。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖框产,靈堂內的尸體忽然破棺而出重慢,到底是詐尸還是另有隱情饥臂,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布似踱,位于F島的核電站隅熙,受9級特大地震影響,放射性物質發(fā)生泄漏核芽。R本人自食惡果不足惜囚戚,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轧简。 院中可真熱鬧驰坊,春花似錦、人聲如沸哮独。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舟扎,卻和暖如春分飞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背睹限。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工譬猫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羡疗。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓染服,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叨恨。 傳聞我的和親對象是個殘疾皇子柳刮,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內容