React Native同步调用Native方法 RCT_EXP
JS调用Native
我们知道,在React Native中,经常需要JS和native交互,在项目RN化的初期,我们在通过JS端编写完页面后,往往还需要调用Native端的方法或属性,来实现一些逻辑交互.
这里我们就介绍一下,JS端调用Native方法的几种情况.
异步方法调用
React Native提供了组件(Module)的概念,Native通过遵守协议<RCTBridgeModule>
,实现RCT_EXPORT_MODULE()
方法来输出组件.
需要注意的是,该类内的属性和方法,模式是不会输出到JS端的,必须单独声明.
输出方法使用RCT_EXPORT_METHOD()
来实现.默认在异步线程调用,可以通过- (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); }
去回归主线程.
如果想拿到返回结果,可以使用callback的方式,
RCT_EXPORT_METHOD(getCacheSize:(RCTResponseSenderBlock)callback){
callback(@[[NSNull null], @(cacheSize)]);
}
在JS的使用为
import { NativeModules } from 'react-native'
const SettingTool = NativeModules.RNSettingTool
SettingTool.getCacheSize((error, events) => {
if (error) {
console.error(error)
} else {
this.setState({cacheSize: events.toFixed(2)})
}
})
这种方式,每次在使用时都需要实现callback的函数,并且无法做同步调用
同步方法调用
RN提供了一个同步调用的方法RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD()
,直接在方法内return 返回值,在前端通过appVersion = PXUserInfoTool.appVersion()
的方式来获得,下面我们讨论一下这个方法的内部实现.
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD()
通过宏定义我们可以看到,同步输出方法,最终是生成了一个RCTMethodInfo并且返回.我们看一下RCTMethodInfo,是一个结构体定义.
typedef struct RCTMethodInfo {
const char *const jsName;
const char *const objcName;
const BOOL isSync;
} RCTMethodInfo;
继续通过RCTMethodInfo内部的isSync参数的使用情况,我们知道在- (id)invokeWithBridge:(RCTBridge *)bridge module:(id)module arguments:(NSArray *)arguments
方法内部用到了.
这个方法是,JS端在调用Native代码时触发的方法,继续查看.
在JS端的实现是在NativeModules.js
内部,在function genMethod(moduleID: number, methodID: number, type: MethodType)
内通过判断三种调用方式实现的.
方法调用分为: Promise, sync, 普通方法.
sync在客户端的调用,是在JSCExecutor.cpp
内的JSValueRef JSCExecutor::nativeCallSyncHook( size_t argumentCount, const JSValueRef arguments[])
方法,
最终调用到了RCTNativeModule.mm
内的MethodCallResult RCTNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic &¶ms)
方法,
进一步,RCTModuleMethod.mm
内的- (id)invokeWithBridge:(RCTBridge *)bridge module:(id)module arguments:(NSArray *)arguments
方法.
全部都是同步执行的,并且注意**手动指定methodQueue对sync方法无效
**