思維導圖-React Native通信原理

React Native通信原理.png

原理

原生端和JS端都保存了一份模塊配置表,里面標記了所有原生暴露的模塊和方法。

  • 實例


    1A8A13D4-E61B-44E5-A33C-FA2990276B5F.png

JS調(diào)用原生模塊方法時,通過模塊配置表把請求分解為模塊ID、方法ID和參數(shù)傳給原生培他,原生通過模塊配置表找到對應的方法并執(zhí)行

React Native結構

286D5081-903E-4564-9A5F-109189CD9C64.png

React Native啟動流程

39649440-586D-481D-9708-90CD5FBBE88A.png

創(chuàng)建RCTBridge

  • 橋接對象,管理JS和OC交互,它內(nèi)部持有一個RCTBatchBridge對象

創(chuàng)建RCTBatchBridge

  • JS和OC交互主要是由它實現(xiàn)的

執(zhí)行[RCTBatchedBridge loadSource]

  • 加載JS源碼

執(zhí)行[RCTBatchedBridge initModulesWithDispatchGroup]

  • 創(chuàng)建模塊配置表

執(zhí)行[RCTJSCExecutor injectJSONText]

  • 往js中注入模塊配置表

執(zhí)行完JS代碼遗座,回調(diào)OC舀凛,調(diào)用OC中的組件

實現(xiàn)過程

原生向js端發(fā)消息

  • RCTEventDispatcher

    • 通過RCTJSExecutor,主動發(fā)起調(diào)用了JS

原生端生成模塊配置表

  • 使用RCT_EXPORT_MODULE宏注冊要暴露的類

    • 宏定義


      A321DE3C-03D1-4B70-A990-D75AA22D90DD.png
    • RCT_EXPORT_MODULE宏中途蒋,app運行時調(diào)用load方法猛遍,注冊自己

      • 把宏展開后的類


        45B5D309-A638-4A9C-B571-1DC9308ED224.png
  • 使用RCT_EXPORT_METHOD宏注冊方法

    • 宏定義


      A5EDE7B5-7DEA-4263-9C40-5A678DB7BCB8.png
    • 該宏返回一個數(shù)組,里面包含方法內(nèi)容

      • 實例


        0C596D90-B24F-44F1-9817-69F3DFD56784.png
      • 把宏展開后的方法


        961D10E6-0CA0-465A-BE68-50AD6388A144.png
  • 全局單例數(shù)組RCTModuleClasses保存了所有的原生類信息

21AA6845-CB76-442C-B703-8BC6AC093E6B.png
  • 從RCTModuleClasses生成三個配置表,保存所有的原生模塊信息懊烤,便于后續(xù)查找

6C216003-4F3E-4AB6-8C69-1D213AC3D81D.png
    - moduleClassesByID數(shù)組表梯醒,存儲原生類的class

    - moduleDataByID數(shù)組表,保存由原生類生成的RCTModuleData對象

    - moduleDataByName字典表腌紧,以+methodName方法的返回值為key茸习,保存由原生類生成的RCTModuleData對象

    - RCTModuleData保存類moduleClass、name壁肋、methods号胚、instance、confige
  • 生成moduleConfig

    • 從moduleDataByName表中浸遗,取出所有項猫胁,放到一個數(shù)組中。

模塊配置表傳到js端

AC697F9A-E79F-4E5A-B713-46EC7B119C4E.png
  • 將moduleConfig配置信息跛锌,通過RCTJSExecutor弃秆,注入到JS環(huán)境JSContext里

  • 在JS的global全局變量里面加入一個__fbBatchedBridgeConfig對象,是一個數(shù)組髓帽,里面記錄著所有原生模塊信息

js端調(diào)用原生模塊

  • 在模塊配置表內(nèi)菠赚,找到js請求中的ModuleID、MethodID氢卡、arguments

91A3C0C8-81B0-40C2-A8B8-28B5B6D11A6C.png
  • js端把方法回調(diào)存入callback數(shù)組中锈至,原生端執(zhí)行完畢,調(diào)用此回調(diào)

E405E7D2-A805-4655-A3F1-E7A1CF5FFDD7.png
  • 把js請求放到MessageQueue中译秦,等待原生調(diào)用

E7246B93-F454-46DB-ACD6-7A8573C3EF89.png
- 間隔5毫秒后才能調(diào)用
CC0F2791-86CA-40BC-9E94-180C0842E2A4.png
  • 原生收到消息峡捡,通過模塊配置表,找到對應的模塊和方法筑悴,調(diào)用執(zhí)行

    • js一次性傳來多條消息们拙,分別識別出每一條消息的module信息

    • 查找到對應的模塊、方法阁吝,執(zhí)行

B316460A-4E05-4E7D-8B8D-D15DC668770C.png
    - 
43D08E94-E58D-4E7E-B661-ED0E33326F13.png
- 原生方法執(zhí)行完畢砚婆,再主動調(diào)用js,js端通過callbackId突勇,找到對應callback調(diào)用

js調(diào)用原生UI組件

  • 原生UI組件注冊

    • 原生UI組件繼承自RCTViewManager

      • RCTViewManager是上面的一個原生模塊装盯,作為基類暴露公用屬性如backgroundColor、opacity甲馋、shadowColor等

      • 子類可以添加自定義的屬性埂奈,供js調(diào)用

    • RCT_EXPORT_VIEW_PROPERTY

      • 宏定義


        887B22C6-7485-4061-971F-69E6363D00EF.png
    • RCTUIManager是上面的一個原生模塊,它管理著所有的原生UI組件的生成定躏、更新

    • RCTUIManager初始化

      • 從模塊配置表中账磺,循環(huán)查找其中繼承自RCTViewManager的對象芹敌,放到_viewManagers字典和_viewConfigs數(shù)組中,key是viewName
  • RCTRootView

    • js環(huán)境加載完成后垮抗,創(chuàng)建subview RCTContentRootView

      • RCTContentRootView通過allocateRootTag方法創(chuàng)建了root得reactTag氏捞,規(guī)則是從1開始,每次累加10

63E57B57-ACE6-40C9-8E71-1E13FD53A442.png
    - 把reactTag放到RCTUIManager的_viewRegistry字典中冒版,key為reactTag

- 通知js開始繪制頁面

    - 
C4D37E32-FBE8-41C0-9ABB-5269A69E94F3.png
  • RCTUIManager

    • 對js暴露的方法

      • createView

        • 創(chuàng)建各種原生View液茎,并且把傳過來的JS的屬性參數(shù)一一賦值
      • updateView

        • JS通知原生View來更新對應的屬性、樣式變化
      • ......

    • js操縱原生view的實現(xiàn)過程

      • 從js端傳來reactTag辞嗡、viewName豁护、props

        • 以createView為例


          0A075817-0BA1-400D-95A4-3479D96E2551.png
      • 通過viewName,在_viewManagers中找到對應的原生view data

      • 創(chuàng)建原生view欲间,指定它的tag為reactTag,方便后續(xù)查找

      • 通過props断部,給原生view賦值

        • 通過propConfig判斷是否注冊過該屬性

        • 如果已注冊猎贴,則通過運行時invocation的方式,生成了一個block函數(shù)蝴光,每次調(diào)用這個block她渴,就會以運行時的方式,setter給對應屬性

AA735048-5774-4495-A1C3-C0EA3BD177D2.png

參考資料:
http://blog.cnbang.net/tech/2698/
http://taobaofed.org/blog/2015/12/30/the-communication-scheme-of-react-native-in-ios/
http://awhisper.github.io/2016/07/02/ReactNative%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%902/

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔑祟,一起剝皮案震驚了整個濱河市趁耗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疆虚,老刑警劉巖苛败,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異径簿,居然都是意外死亡罢屈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門篇亭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缠捌,“玉大人,你說我怎么就攤上這事译蒂÷拢” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵柔昼,是天一觀的道長哑芹。 經(jīng)常有香客問我,道長岳锁,這世上最難降的妖魔是什么绩衷? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任蹦魔,我火速辦了婚禮,結果婚禮上咳燕,老公的妹妹穿的比我還像新娘勿决。我一直安慰自己,他們只是感情好招盲,可當我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布低缩。 她就那樣靜靜地躺著,像睡著了一般曹货。 火紅的嫁衣襯著肌膚如雪咆繁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天顶籽,我揣著相機與錄音玩般,去河邊找鬼。 笑死礼饱,一個胖子當著我的面吹牛坏为,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镊绪,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼匀伏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝴韭?” 一聲冷哼從身側響起够颠,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榄鉴,沒想到半個月后履磨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡牢硅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年蹬耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片减余。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡综苔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出位岔,到底是詐尸還是另有隱情如筛,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布抒抬,位于F島的核電站杨刨,受9級特大地震影響,放射性物質發(fā)生泄漏擦剑。R本人自食惡果不足惜妖胀,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一芥颈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赚抡,春花似錦爬坑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赁遗,卻和暖如春署辉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岩四。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工哭尝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人剖煌。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓刚夺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親末捣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容