React Native同步调用Native方法 RCT_EXP

2018-12-10  本文已影响99人  sea_biscute

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 &&params)方法,
进一步,RCTModuleMethod.mm内的- (id)invokeWithBridge:(RCTBridge *)bridge module:(id)module arguments:(NSArray *)arguments方法.

全部都是同步执行的,并且注意**手动指定methodQueue对sync方法无效
**

上一篇下一篇

猜你喜欢

热点阅读