| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 【React Native】深入理解Native与RN通信原理 -> 正文阅读 |
|
[移动开发]【React Native】深入理解Native与RN通信原理 |
? ? ? ? 在使用 React Native 开发应用程序的时候,有时候需要使用?JavaScript 中默认不可用的 IOS 或 Android 的原生 API。 也许你想复用一些现有的 OC、Swift、Java 或 C++ 库,而不必在 JavaScript 中重新实现它,或者为图像处理之类的事情编写一些高性能、多线程的代码。那么此时就不得不与Native打交道了。 ? ? ? ? 幸运的是,React Native已经提供了这样的能力来供你使用,在JS Core的强大支持下,我们RN侧可以使用NativeModule 来将Native代码作为 JS 对象暴露给 JavaScript来调用,从而允许您从 JS 内可以调用Native代码。 ? ? ? ? 作为非原生开发,虽然我们不希望此功能成为通常开发过程的一部分,但它的存在至关重要。 并且如果 React Native 没有导出你的应用程序需要的原生 API,那么你应该能够自己封装并且导出它! 下面,我们来深入聊一聊RN的初始化阶段,以及原生端与JS端互相通信的过程。 JS Core????????开始之前,我觉得有必要简单介绍一下JS Core,众所周知,RN是通过JavaScriptCore提供的能力来与native交互的,JavaScript Core(简称 JSCore)是一个开源的框架,是?WebKit?的一部分,用最简单的话描述这个框架,它大概提供了两种能力:
????????JSExport 是整个 JSCore 里面最神奇的部分,也正是有了 JSExport 才让我们把 Native 对象暴露给 JS 环境非常的容易,简单说,通过JSExport我们可以把 Native 对象的属性和方法暴露给 JS 环境,先来看一段OC的接口代码:
????????NativeObject 可以被实现为任意的对象,只要他实现了NativeObjectExport那么这个协议里面的属性和对象就可以直接被 JS 环境使用,例如上面的 property1 和 method1。我们只要在 context 里面注入一个NativeObject的对象,就可以在 JS 环境放肆的与 Native 进行交互了:
在JS的环境中
????????当Native代码执行完 method1之后,可以通过这个 handler 回调到 JS 环境,JS 环境通过 function 的 object 拿到返回结果,这就是一个完整的流程。 初始化阶段? ? ? ? 在RN初始化阶段,首先原生端会遍历开发者自定义的原生模块与RN框架提供的原生模块,将其注册到一张原生模块映射表中,然后,原生端也会将需要调用的JS模块注册到一张JS模块映射表中,需要注意的是,原生端并没有实现JS Module,只是有一份接口而已(Android需要实现JS接口,但是IOS不需要)。 ? ? ? ? 紧接着JS Core会将两份映射表传入到JS侧,在JS侧,原生模块映射表会绑定到RN的提供的NativeModule上面,这样JS就可以通过NativeModule来调用Native提供的API了,对于JS模块映射表来说,JS侧会实现对应的JS方法,并注册进去。这样,Native就可以调用JS提供的方法了。并且JS可以以回调参数的形式来接受Native传来的数据。 请看源码:
????????这是一段从Native SDK里拿出来的源码,可以看到,GAActionSheet就是native暴露的api,createNoop方法只是为了在native api还没加载完成时就调用时的一种兜底方案。
? ? ? ? 相应地,上述代码展示了怎样通过ReactNative提供的NativeEventEmitter来订阅一个JS事件。 ????????附一段react native源码来解释NativeModules到底是什么,由于React Native源码较多,已被我删减了很多,感兴趣的同学可以去react-native/Libraries/BatchedBridge/NativeModules.js底下查看,可以看到,NativeModules正是所谓的“原生模块映射表”。 ? ? ? ? 另外,可以看到,通过global全局对象可以注册JS函数供Native调用,JS可以通过global来获取Native传递过来的数据。
????????这里展示了JSCore中如何获取并执行JS中注册好的global.__fbGenNativeModule = genModule
原生端调用JS? ? ? ? ?接下来看一下原生端怎样调用JS,首先,Native在初始化时候创建好的JS模块映射表中找到需要被调用的JSModule_1,然后通过JSCore来传递被调用的模块名、方法名以及参数,传递到JS侧,JS在JS模块映射表中找到提前注册好的JSModule_1,然后执行并传入参数。这就是一个完整的原生端向JS端通信的过程。 JS端调用原生代码????????类似地,看一下JS怎样调用Native方法,首先,JS在初始化时传过来的原生模块映射表中找到需要调用的NativeModule_1,然后通过JSCore传递被调用的模块名方法名以及参数到Native侧,Native拿到方法名之后找到注册好的NativeModule_1,然后执行相应的Native方法并传入参数。 ? ? ? ? 那么,有人会想,在Native侧执行完之后,如果有返回值,怎么将返回值传到JS侧呢?当JS侧调用原生代码有返回值的时候,流程会相对复杂一些: ? ? ? ? ?如图,可以清晰的看到,如果有返回值的时候,在JS调用NativeModule_1的时候会生成一个回调ID,并将回调ID一起传递给Native,这个回调ID就是用来标识当Native传递执行结果时,JS拿到执行结果后,将执行结果分发给哪个JS变量。 接下来我们看一下JS是怎么注册到JS模块映射表中的:
????????可以看到JS方法是通过调用__fbBatchedBridge上面的registerCallableModule函数来注册的,翻到RN源码的react-native/Libraries/BatchedBridge/BatchedBridge.js处,你会发现,__fbBatchedBridge其实就是一个消息队列,registerCallableModule就是往表里添加一项而已。
????????下面看一下Android里是怎样调用JS方法的,可以看到在Android里先定义了JS模块的接口。
? ? ? ? 在IOS内调用JS十分简单:
? 参考资料 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 5:36:36- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |