mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-14 23:18:06 +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
@@ -0,0 +1,159 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
package com.facebook.react.cxxbridge;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.common.futures.SimpleSettableFuture;
|
||||
import com.facebook.react.module.model.Info;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
|
||||
import static com.facebook.infer.annotation.Assertions.assertNotNull;
|
||||
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
|
||||
/**
|
||||
* Holder to enable us to lazy create native modules.
|
||||
*
|
||||
* This works by taking a provider instead of an instance, when it is first required we'll create
|
||||
* and initialize it. Initialization currently always happens on the UI thread but this is due to
|
||||
* change for performance reasons.
|
||||
*
|
||||
* Lifecycle events via a {@link LifecycleEventListener} will still always happen on the UI thread.
|
||||
*/
|
||||
public class ModuleHolder {
|
||||
|
||||
private final Info mInfo;
|
||||
private @Nullable Provider<? extends NativeModule> mProvider;
|
||||
private @Nullable NativeModule mModule;
|
||||
private boolean mInitializeNeeded;
|
||||
|
||||
public ModuleHolder(
|
||||
Class<? extends NativeModule> clazz,
|
||||
@Nullable ReactModuleInfo reactModuleInfo,
|
||||
Provider<? extends NativeModule> provider) {
|
||||
mInfo = reactModuleInfo == null ? new LegacyModuleInfo(clazz) : reactModuleInfo;
|
||||
mProvider = provider;
|
||||
|
||||
if (mInfo.needsEagerInit()) {
|
||||
mModule = doCreate();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void initialize() {
|
||||
if (mModule != null) {
|
||||
doInitialize(mModule);
|
||||
} else {
|
||||
mInitializeNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void destroy() {
|
||||
if (mModule != null) {
|
||||
mModule.onCatalystInstanceDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
public Info getInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
public synchronized NativeModule getModule() {
|
||||
if (mModule == null) {
|
||||
mModule = doCreate();
|
||||
}
|
||||
return mModule;
|
||||
}
|
||||
|
||||
private NativeModule doCreate() {
|
||||
NativeModule module = create();
|
||||
mProvider = null;
|
||||
return module;
|
||||
}
|
||||
|
||||
private NativeModule create() {
|
||||
String name = mInfo instanceof LegacyModuleInfo ?
|
||||
((LegacyModuleInfo) mInfo).mType.getSimpleName() :
|
||||
mInfo.name();
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createModule")
|
||||
.arg("name", name)
|
||||
.flush();
|
||||
NativeModule module = assertNotNull(mProvider).get();
|
||||
if (mInitializeNeeded) {
|
||||
doInitialize(module);
|
||||
mInitializeNeeded = false;
|
||||
}
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
return module;
|
||||
}
|
||||
|
||||
private void doInitialize(NativeModule module) {
|
||||
SystraceMessage.Builder section =
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initialize");
|
||||
if (module instanceof CxxModuleWrapper) {
|
||||
section.arg("className", module.getClass().getSimpleName());
|
||||
} else {
|
||||
section.arg("name", mInfo.name());
|
||||
}
|
||||
section.flush();
|
||||
callInitializeOnUiThread(module);
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
|
||||
// TODO(t11394264): Use the native module thread here after the old bridge is gone
|
||||
private static void callInitializeOnUiThread(final NativeModule module) {
|
||||
if (UiThreadUtil.isOnUiThread()) {
|
||||
module.initialize();
|
||||
return;
|
||||
}
|
||||
final SimpleSettableFuture<Void> future = new SimpleSettableFuture<>();
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeOnUiThread");
|
||||
try {
|
||||
module.initialize();
|
||||
future.set(null);
|
||||
} catch (Exception e) {
|
||||
future.setException(e);
|
||||
}
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
});
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private class LegacyModuleInfo implements Info {
|
||||
|
||||
public final Class<?> mType;
|
||||
|
||||
public LegacyModuleInfo(Class<?> type) {
|
||||
mType = type;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return getModule().getName();
|
||||
}
|
||||
|
||||
public boolean canOverrideExistingModule() {
|
||||
return getModule().canOverrideExistingModule();
|
||||
}
|
||||
|
||||
public boolean supportsWebWorkers() {
|
||||
return getModule().supportsWebWorkers();
|
||||
}
|
||||
|
||||
public boolean needsEagerInit() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user