Files
react-native/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/JavaModuleWrapper.java
Aaron Chiu 797ca6c219 Add ability to lazy load Native Java Modules
Summary: Utilizes the build time annotation processor ReactModuleSpecProcessor that creates ReactModuleInfos for modules annotated with ReactModule and listed in the ReactModuleList annotation of LazyReactPackages. This way we don't have to instantiate the native modules to get the name, canOverrideExistingModule, and supportsWebWorkers values of the native modules. In the NativeModuleRegistry, we either store these ReactModuleInfos inside of a ModuleHolder or if we can't get the ReactModuleInfo for a specific module we instantiate that module to get the values (as we previously did) to store in a LegacyModuleInfo.

Reviewed By: astreet

Differential Revision: D3796561

fbshipit-source-id: f8fb9b4993f59b51ce595eb2f2c3425129b28ce5
2016-09-23 15:58:46 -07:00

161 lines
4.8 KiB
Java

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.cxxbridge;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.BaseJavaModule;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.ExecutorToken;
import com.facebook.react.bridge.NativeArray;
import com.facebook.react.bridge.ReadableNativeArray;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
/**
* This is part of the glue which wraps a java BaseJavaModule in a C++
* NativeModule. This could all be in C++, but it's android-specific
* initialization code, and writing it this way is easier to read and means
* fewer JNI calls.
*/
@DoNotStrip
/* package */ class JavaModuleWrapper {
@DoNotStrip
public class MethodDescriptor {
@DoNotStrip
Method method;
@DoNotStrip
String signature;
@DoNotStrip
String name;
@DoNotStrip
String type;
}
private final CatalystInstance mCatalystInstance;
private final ModuleHolder mModuleHolder;
private final ArrayList<BaseJavaModule.JavaMethod> mMethods;
public JavaModuleWrapper(CatalystInstance catalystinstance, ModuleHolder moduleHolder) {
mCatalystInstance = catalystinstance;
mModuleHolder = moduleHolder;
mMethods = new ArrayList<>();
}
@DoNotStrip
public BaseJavaModule getModule() {
return (BaseJavaModule) mModuleHolder.getModule();
}
@DoNotStrip
public String getName() {
return mModuleHolder.getInfo().name();
}
@DoNotStrip
public List<MethodDescriptor> getMethodDescriptors() {
ArrayList<MethodDescriptor> descs = new ArrayList<>();
for (Map.Entry<String, BaseJavaModule.NativeMethod> entry :
getModule().getMethods().entrySet()) {
MethodDescriptor md = new MethodDescriptor();
md.name = entry.getKey();
md.type = entry.getValue().getType();
BaseJavaModule.JavaMethod method = (BaseJavaModule.JavaMethod) entry.getValue();
mMethods.add(method);
descs.add(md);
}
return descs;
}
@DoNotStrip
public List<MethodDescriptor> newGetMethodDescriptors() {
ArrayList<MethodDescriptor> descs = new ArrayList<>();
for (Map.Entry<String, BaseJavaModule.NativeMethod> entry :
getModule().getMethods().entrySet()) {
MethodDescriptor md = new MethodDescriptor();
md.name = entry.getKey();
md.type = entry.getValue().getType();
BaseJavaModule.JavaMethod method = (BaseJavaModule.JavaMethod) entry.getValue();
md.method = method.getMethod();
md.signature = method.getSignature();
descs.add(md);
}
for (Map.Entry<String, BaseJavaModule.SyncNativeHook> entry :
getModule().getSyncHooks().entrySet()) {
MethodDescriptor md = new MethodDescriptor();
md.name = entry.getKey();
md.type = BaseJavaModule.METHOD_TYPE_SYNC;
BaseJavaModule.SyncJavaHook method = (BaseJavaModule.SyncJavaHook) entry.getValue();
md.method = method.getMethod();
md.signature = method.getSignature();
descs.add(md);
}
return descs;
}
// TODO mhorowitz: make this return NativeMap, which requires moving
// NativeMap out of OnLoad.
@DoNotStrip
public NativeArray getConstants() {
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "Map constants")
.arg("moduleName", getName())
.flush();
Map<String, Object> map = getModule().getConstants();
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "WritableNativeMap constants")
.arg("moduleName", getName())
.flush();
WritableNativeMap writableNativeMap;
try {
writableNativeMap = Arguments.makeNativeMap(map);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
WritableNativeArray array = new WritableNativeArray();
array.pushMap(writableNativeMap);
return array;
}
@DoNotStrip
public boolean supportsWebWorkers() {
return getModule().supportsWebWorkers();
}
@DoNotStrip
public void invoke(ExecutorToken token, int methodId, ReadableNativeArray parameters) {
if (mMethods == null || methodId >= mMethods.size()) {
return;
}
mMethods.get(methodId).invoke(mCatalystInstance, token, parameters);
}
}