mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-08 22:42:05 +08:00
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
This commit is contained in:
committed by
Facebook Github Bot 3
parent
1f9b765f81
commit
797ca6c219
@@ -14,8 +14,10 @@ import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@@ -35,6 +37,7 @@ import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.JavaJSExecutor;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.JavaScriptModuleRegistry;
|
||||
import com.facebook.react.bridge.ModuleSpec;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
|
||||
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
|
||||
@@ -61,6 +64,8 @@ import com.facebook.react.devsupport.DevSupportManager;
|
||||
import com.facebook.react.devsupport.DevSupportManagerFactory;
|
||||
import com.facebook.react.devsupport.ReactInstanceDevCommandsHandler;
|
||||
import com.facebook.react.devsupport.RedBoxHandler;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.modules.debug.DeveloperSettings;
|
||||
@@ -72,6 +77,7 @@ import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START;
|
||||
@@ -107,6 +113,8 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
*/
|
||||
/* package */ class XReactInstanceManagerImpl extends ReactInstanceManager {
|
||||
|
||||
private static final String TAG = XReactInstanceManagerImpl.class.getSimpleName();
|
||||
|
||||
/* should only be accessed from main thread (UI thread) */
|
||||
private final List<ReactRootView> mAttachedRootViews = new ArrayList<>();
|
||||
private LifecycleState mLifecycleState;
|
||||
@@ -836,7 +844,8 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
FLog.i(ReactConstants.TAG, "Creating react context.");
|
||||
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START);
|
||||
mSourceUrl = jsBundleLoader.getSourceUrl();
|
||||
NativeModuleRegistry.Builder nativeRegistryBuilder = new NativeModuleRegistry.Builder();
|
||||
List<ModuleSpec> moduleSpecs = new ArrayList<>();
|
||||
Map<Class, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
JavaScriptModuleRegistry.Builder jsModulesBuilder = new JavaScriptModuleRegistry.Builder();
|
||||
|
||||
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
|
||||
@@ -851,7 +860,12 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
try {
|
||||
CoreModulesPackage coreModulesPackage =
|
||||
new CoreModulesPackage(this, mBackBtnHandler, mUIImplementationProvider);
|
||||
processPackage(coreModulesPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
|
||||
processPackage(
|
||||
coreModulesPackage,
|
||||
reactContext,
|
||||
moduleSpecs,
|
||||
reactModuleInfoMap,
|
||||
jsModulesBuilder);
|
||||
} finally {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
@@ -862,7 +876,12 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
TRACE_TAG_REACT_JAVA_BRIDGE,
|
||||
"createAndProcessCustomReactPackage");
|
||||
try {
|
||||
processPackage(reactPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
|
||||
processPackage(
|
||||
reactPackage,
|
||||
reactContext,
|
||||
moduleSpecs,
|
||||
reactModuleInfoMap,
|
||||
jsModulesBuilder);
|
||||
} finally {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
@@ -873,7 +892,7 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "buildNativeModuleRegistry");
|
||||
NativeModuleRegistry nativeModuleRegistry;
|
||||
try {
|
||||
nativeModuleRegistry = nativeRegistryBuilder.build();
|
||||
nativeModuleRegistry = new NativeModuleRegistry(moduleSpecs, reactModuleInfoMap);
|
||||
} finally {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_END);
|
||||
@@ -939,14 +958,78 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
private void processPackage(
|
||||
ReactPackage reactPackage,
|
||||
ReactApplicationContext reactContext,
|
||||
NativeModuleRegistry.Builder nativeRegistryBuilder,
|
||||
List<ModuleSpec> moduleSpecs,
|
||||
Map<Class, ReactModuleInfo> reactModuleInfoMap,
|
||||
JavaScriptModuleRegistry.Builder jsModulesBuilder) {
|
||||
for (NativeModule nativeModule : reactPackage.createNativeModules(reactContext)) {
|
||||
nativeRegistryBuilder.add(nativeModule);
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processPackage")
|
||||
.arg("className", reactPackage.getClass().getSimpleName())
|
||||
.flush();
|
||||
if (mLazyNativeModulesEnabled && reactPackage instanceof LazyReactPackage) {
|
||||
LazyReactPackage lazyReactPackage = (LazyReactPackage) reactPackage;
|
||||
if (addReactModuleInfos(lazyReactPackage, reactContext, moduleSpecs, reactModuleInfoMap)) {
|
||||
moduleSpecs.addAll(lazyReactPackage.getNativeModules(reactContext));
|
||||
}
|
||||
} else {
|
||||
FLog.d(
|
||||
ReactConstants.TAG,
|
||||
reactPackage.getClass().getSimpleName() +
|
||||
" is not a LazyReactPackage, falling back to old version");
|
||||
addEagerModuleProviders(reactPackage, reactContext, moduleSpecs);
|
||||
}
|
||||
|
||||
for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) {
|
||||
jsModulesBuilder.add(jsModuleClass);
|
||||
}
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
|
||||
private boolean addReactModuleInfos(
|
||||
LazyReactPackage lazyReactPackage,
|
||||
ReactApplicationContext reactApplicationContext,
|
||||
List<ModuleSpec> moduleSpecs,
|
||||
Map<Class, ReactModuleInfo> reactModuleInfoMap) {
|
||||
Class<?> reactModuleInfoProviderClass = null;
|
||||
try {
|
||||
reactModuleInfoProviderClass = Class.forName(
|
||||
lazyReactPackage.getClass().getCanonicalName() + "$$ReactModuleInfoProvider");
|
||||
} catch (ClassNotFoundException e) {
|
||||
FLog.w(
|
||||
TAG,
|
||||
"Could not find generated ReactModuleInfoProvider for " + lazyReactPackage.getClass());
|
||||
// Fallback to non-lazy method.
|
||||
addEagerModuleProviders(lazyReactPackage, reactApplicationContext, moduleSpecs);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reactModuleInfoProviderClass != null) {
|
||||
ReactModuleInfoProvider instance;
|
||||
try {
|
||||
instance = (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(
|
||||
"Unable to instantiate ReactModuleInfoProvider for " + lazyReactPackage.getClass(),
|
||||
e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(
|
||||
"Unable to instantiate ReactModuleInfoProvider for " + lazyReactPackage.getClass(),
|
||||
e);
|
||||
}
|
||||
Map<Class, ReactModuleInfo> map = instance.getReactModuleInfos();
|
||||
if (!map.isEmpty()) {
|
||||
reactModuleInfoMap.putAll(map);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addEagerModuleProviders(
|
||||
ReactPackage reactPackage,
|
||||
ReactApplicationContext reactApplicationContext,
|
||||
List<ModuleSpec> moduleSpecs) {
|
||||
for (NativeModule nativeModule : reactPackage.createNativeModules(reactApplicationContext)) {
|
||||
moduleSpecs.add(
|
||||
new ModuleSpec(nativeModule.getClass(), new EagerModuleProvider(nativeModule)));
|
||||
}
|
||||
}
|
||||
|
||||
private void moveReactContextToCurrentLifecycleState() {
|
||||
|
||||
Reference in New Issue
Block a user