【用友iUAP專(zhuān)家講堂】解析React Native內(nèi)部通訊機(jī)制
React Native是Facebook發(fā)布的一個(gè)用JavaScript開(kāi)發(fā)移動(dòng)應(yīng)用的開(kāi)源框架??蚣苣壳爸恢С謎OS平臺(tái),但一經(jīng)推出,便受到國(guó)內(nèi)外移動(dòng)開(kāi)發(fā)者的追捧,從GitHub上的統(tǒng)計(jì)數(shù)據(jù)看,自React Native開(kāi)源至今的3個(gè)月時(shí)間,已經(jīng)有170位貢獻(xiàn)者對(duì)項(xiàng)目進(jìn)行了1790余次的提交。
在React Native之前,基于JavaScript開(kāi)發(fā)跨平臺(tái)移動(dòng)應(yīng)用的框架已經(jīng)有很多,這些框架都采用構(gòu)建WEB頁(yè)面的方式,但由于DOM性能和瀏覽器單線程處理等問(wèn)題,構(gòu)建的應(yīng)用在移動(dòng)端體驗(yàn)差,雖然開(kāi)發(fā)成本很低,仍然無(wú)法取代原生開(kāi)發(fā)。React Native與其他框架不同,它使用JavaScript來(lái)調(diào)用原生控件,使應(yīng)用運(yùn)行在本地環(huán)境中,從而使應(yīng)用在移動(dòng)端的體驗(yàn)堪比原生應(yīng)用。
React Native由于使用JavaScript調(diào)用原生控件,運(yùn)行過(guò)程中需要JavaScript和原生語(yǔ)言進(jìn)行頻繁、高效的通訊。這一過(guò)程極其復(fù)雜,下面以iOS為例詳述其過(guò)程。
React Native內(nèi)部通訊機(jī)制圖解
React Native使用了iOS自帶的JavaScriptCore作為JS解析的引擎,但并未使用其提供的OC-JS(OC,即Object-C;JS,即JavaScript)通訊機(jī)制,而是自己實(shí)現(xiàn)了一套機(jī)制。在通訊機(jī)制中有一個(gè)稱為模塊配置表的配置文件,這個(gè)文件中記錄了OC中可供JS調(diào)用的模塊和方法。在OC和JS中分別有一個(gè)通訊橋,每個(gè)通訊橋中存儲(chǔ)著一份模塊配置表,這是OC-JS通訊的基礎(chǔ)。詳細(xì)的調(diào)用過(guò)程是這樣的:
1、事件觸發(fā)JS函數(shù)調(diào)用,事件包含定時(shí)事件、加載事件等。
2、JS通訊橋?qū)φ{(diào)用進(jìn)行分析,把調(diào)用的模塊、方法解析成模塊ID、方法ID
3、JS通訊橋根據(jù)返回函數(shù)生成返回函數(shù)ID,再聯(lián)合調(diào)用參數(shù)、模塊ID、方法ID生成一個(gè)消息模型,然后將模型置于消息隊(duì)列中,等待OC來(lái)讀取。
4、OC通訊橋調(diào)用JS的某個(gè)方法時(shí),JS在返回?cái)?shù)據(jù)中插入消息隊(duì)列的數(shù)據(jù),OC在消息隊(duì)列中將消息模型取出。
5、OC根據(jù)模塊配置表解析消息模型,找到OC中對(duì)應(yīng)的模塊和方法。
6. RCTModuleMethod對(duì)象對(duì)傳遞的JS參數(shù)進(jìn)行轉(zhuǎn)換和組裝處理,然后通過(guò)NSInvocation動(dòng)態(tài)調(diào)用OC方法,同時(shí)RCTModuleMethod生成block回調(diào)對(duì)象。
7、OC方法調(diào)用技術(shù)后,獲取調(diào)用的返回值和返回函數(shù)ID,執(zhí)行block回調(diào)。
8、block執(zhí)行JS消息隊(duì)列固有的函數(shù)回調(diào)方法,并將返回函數(shù)ID和返回值傳遞給該方法。
9、JS消息隊(duì)列根據(jù)返回函數(shù)ID,找到對(duì)應(yīng)的JS函數(shù)。
10、調(diào)用該JS函數(shù),傳遞返回值,完成回調(diào)。
在第4步中并未采用JS直接調(diào)用OC的方式,而是使用了消息隊(duì)列來(lái)存儲(chǔ)JS對(duì)OC的調(diào)用并等待OC讀取,這表明在React Native中,OC與JS通訊是單向的。這一過(guò)程是建立在嚴(yán)格的事件響應(yīng)機(jī)制基礎(chǔ)上的:只有在事件觸發(fā)的時(shí)候,JS代碼才會(huì)執(zhí)行,由于采用了原生控件,事件觸發(fā)的時(shí)候,OC程序必然也會(huì)運(yùn)行,OC去調(diào)用JS,便可將JS消息隊(duì)列中的消息全部讀取并處理。在這個(gè)過(guò)程中,JS充當(dāng)了數(shù)據(jù)源的角色,OC是控制器,調(diào)用JS數(shù)據(jù)源并進(jìn)行解析,然后映射到對(duì)應(yīng)OC模塊上。
以上過(guò)程便是JavaScript和Object-C通訊的全部過(guò)程細(xì)節(jié),整個(gè)過(guò)程的關(guān)鍵點(diǎn)在于:模塊化、ID傳遞、封裝調(diào)用、事件響應(yīng)。這一個(gè)過(guò)程確實(shí)很復(fù)雜,但得益于JavaScriptCore和Object-C的高性能,相比于WEB頁(yè)面的DOM操作,這一過(guò)程運(yùn)行極為高效,體驗(yàn)幾乎媲美原生應(yīng)用。