当前分析的ReactNative版本为0.61.5:
ReactNative中为了能访问原生功能模块,它提供了NativeModule接口,看下该接口的定义,实现比较简单,直接继承它的两个类分别是BaseJavaModule和CxxModuleWrapperBase。
从名字能推断,一个是直接通过原生层实现提供Native功能。另一个是通过c++实现。
目前ReactNative仅仅提供了原生层的接口,供开发者使用,当然c++的native也能用,只是官网没有直接提供,后续我也会讲讲如何通过c++实现native功能。
下面我们来介绍今天的主角 JavaScriptModule~
从定义上看,它是个接口,而且是无任何方法的接口,看到瞬间懵圈,看看它的接口说明:
/**
* Interface denoting that a class is the interface to a module with the same name in JS. Calling
* functions on this interface will result in corresponding methods in JS being called.
*
* <p>When extending JavaScriptModule and registering it with a CatalystInstance, all public methods
* are assumed to be implemented on a JS module with the same name as this class. Calling methods on
* the object returned from {@link ReactContext#getJSModule} or {@link CatalystInstance#getJSModule}
* will result in the methods with those names exported by that module being called in JS.
*
* <p>NB: JavaScriptModule does not allow method name overloading because JS does not allow method
* name overloading.
*/
@DoNotStrip
public interface JavaScriptModule {
}
原生层Java任何实现该接口的类或接口,对应到javascript层,都会有个与之一一对应的类,提供js层使用。我们拿RCTDeviceEventEmitter举例,先看它的定义:
public interface RCTDeviceEventEmitter extends JavaScriptModule {
void emit(@NonNull String eventName, @Nullable Object data);
}
很简单,定义一个RCTDeviceEventEmitter接口,并继承JavaScriptModule接口,并提供emit方法,那么对应到js层,也会有与之对应的类和对应的方法。
今天我们主要讲Java层,如何拦截该方法,并转换成消息发送给c++层。后续会讲,c++如何将消息,转化为js层对应方法的调用。
我们看下RCTDeviceEventEmitter使用场景。
mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, eventData);
如上代码,使用场景是直接通过Context找到对应的JSModule,然后调用对应的方法。
接下来我们分成两部分来分析:
1.context如何获取
2.getJSModule方法的实现
一、context如何获取
一般原生层的NativeModule都不会直接继承BaseJavaModule,而是直接继承ReactContextBaseJavaModule,而该类构造函数就会传入ReactApplicationContext,我们看到该类直接继承ReactContext,所以任何原生层提供的NativeModule,都会引用ReactApplicationContext,从而间接引用ReactContext。
二、getJSModule方法
1.ReactContext调用getJSModule实现如下:
public <T extends JavaScriptModule