mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-09 22:43:10 +08:00
Reviewed By: andreicoman11 Differential Revision: D3928797 fbshipit-source-id: d1c6c024c4994b237155f16e6a915b16f216d56d
168 lines
4.8 KiB
Java
168 lines
4.8 KiB
Java
// 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.bridge.ReactMarker;
|
|
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.react.bridge.ReactMarkerConstants.CREATE_MODULE_END;
|
|
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_MODULE_START;
|
|
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() {
|
|
boolean isEagerModule = mInfo instanceof LegacyModuleInfo;
|
|
String name = isEagerModule ? ((LegacyModuleInfo) mInfo).mType.getSimpleName() : mInfo.name();
|
|
if (!isEagerModule) {
|
|
ReactMarker.logMarker(CREATE_MODULE_START);
|
|
}
|
|
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);
|
|
if (!isEagerModule) {
|
|
ReactMarker.logMarker(CREATE_MODULE_END);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|