Channge interface to getNativeModule to use strings instead of classes
Summary: Now that NativeModules are stored based on String keys instead of classnames, the old innterface to getNativeModules(Class moduleInterface) is deprecated. This interface is also incorrect since a native module with the same name may be overridden, causing issues. Getting native modules by name is also similar to what JavaScript does Reviewed By: achen1 Differential Revision: D9697827 fbshipit-source-id: ff832bd2ea5e1c7cfe7d8c0c3a66f0d755b2c354
This commit is contained in:
parent
5f31a1082b
commit
0cd3994f1a
|
@ -63,6 +63,7 @@ public interface CatalystInstance
|
||||||
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
|
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
|
||||||
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
|
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
|
||||||
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
|
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
|
||||||
|
NativeModule getNativeModule(String moduleName);
|
||||||
<T extends JSIModule> T getJSIModule(Class<T> jsiModuleInterface);
|
<T extends JSIModule> T getJSIModule(Class<T> jsiModuleInterface);
|
||||||
Collection<NativeModule> getNativeModules();
|
Collection<NativeModule> getNativeModules();
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,11 @@ import com.facebook.react.bridge.queue.ReactQueueConfigurationImpl;
|
||||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
||||||
import com.facebook.react.common.ReactConstants;
|
import com.facebook.react.common.ReactConstants;
|
||||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||||
|
import com.facebook.react.module.annotations.ReactModule;
|
||||||
import com.facebook.systrace.Systrace;
|
import com.facebook.systrace.Systrace;
|
||||||
import com.facebook.systrace.TraceListener;
|
import com.facebook.systrace.TraceListener;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.Native;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -422,13 +425,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
||||||
return mNativeModuleRegistry.hasModule(nativeModuleInterface);
|
return mNativeModuleRegistry.hasModule(getNameFromAnnotation(nativeModuleInterface));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only ever called with UIManagerModule or CurrentViewerModule.
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
|
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
|
||||||
return mNativeModuleRegistry.getModule(nativeModuleInterface);
|
return (T) mNativeModuleRegistry.getModule(getNameFromAnnotation(nativeModuleInterface));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NativeModule getNativeModule(String moduleName) {
|
||||||
|
return mNativeModuleRegistry.getModule(moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface){
|
||||||
|
ReactModule annotation = nativeModuleInterface.getAnnotation(ReactModule.class);
|
||||||
|
if (annotation == null) {
|
||||||
|
throw new IllegalArgumentException("Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
|
||||||
|
}
|
||||||
|
return annotation.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only used by com.facebook.react.modules.common.ModuleDataCleaner
|
// This is only used by com.facebook.react.modules.common.ModuleDataCleaner
|
||||||
|
|
|
@ -1,39 +1,32 @@
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
*
|
*
|
||||||
* This source code is licensed under the MIT license found in the
|
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||||
* LICENSE file in the root directory of this source tree.
|
* directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.facebook.react.bridge;
|
package com.facebook.react.bridge;
|
||||||
|
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
import com.facebook.react.module.annotations.ReactModule;
|
import com.facebook.react.module.annotations.ReactModule;
|
||||||
import com.facebook.systrace.Systrace;
|
import com.facebook.systrace.Systrace;
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/** A set of Java APIs to expose to a particular JavaScript instance. */
|
||||||
* A set of Java APIs to expose to a particular JavaScript instance.
|
|
||||||
*/
|
|
||||||
public class NativeModuleRegistry {
|
public class NativeModuleRegistry {
|
||||||
|
|
||||||
private final ReactApplicationContext mReactApplicationContext;
|
private final ReactApplicationContext mReactApplicationContext;
|
||||||
private final Map<String, ModuleHolder> mModules;
|
private final Map<String, ModuleHolder> mModules;
|
||||||
|
|
||||||
public NativeModuleRegistry(
|
public NativeModuleRegistry(
|
||||||
ReactApplicationContext reactApplicationContext,
|
ReactApplicationContext reactApplicationContext, Map<String, ModuleHolder> modules) {
|
||||||
Map<String, ModuleHolder> modules) {
|
|
||||||
mReactApplicationContext = reactApplicationContext;
|
mReactApplicationContext = reactApplicationContext;
|
||||||
mModules = modules;
|
mModules = modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Private getters for combining NativeModuleRegistrys */
|
||||||
* Private getters for combining NativeModuleRegistrys
|
|
||||||
*/
|
|
||||||
private Map<String, ModuleHolder> getModuleMap() {
|
private Map<String, ModuleHolder> getModuleMap() {
|
||||||
return mModules;
|
return mModules;
|
||||||
}
|
}
|
||||||
|
@ -42,12 +35,10 @@ public class NativeModuleRegistry {
|
||||||
return mReactApplicationContext;
|
return mReactApplicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ Collection<JavaModuleWrapper> getJavaModules(
|
/* package */ Collection<JavaModuleWrapper> getJavaModules(JSInstance jsInstance) {
|
||||||
JSInstance jsInstance) {
|
|
||||||
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
|
ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
|
||||||
for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
|
for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
|
||||||
if (!entry.getValue().isCxxModule()) {
|
if (!entry.getValue().isCxxModule()) {
|
||||||
//if (!CxxModuleWrapperBase.class.isAssignableFrom(entry.getValue().getModule().getClass())) {
|
|
||||||
javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
|
javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,12 +56,13 @@ public class NativeModuleRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds any new modules to the current module registry
|
* Adds any new modules to the current module registry
|
||||||
*/
|
*/
|
||||||
/* package */ void registerModules(NativeModuleRegistry newRegister) {
|
/* package */ void registerModules(NativeModuleRegistry newRegister) {
|
||||||
|
|
||||||
Assertions.assertCondition(mReactApplicationContext.equals(newRegister.getReactApplicationContext()),
|
Assertions.assertCondition(
|
||||||
"Extending native modules with non-matching application contexts.");
|
mReactApplicationContext.equals(newRegister.getReactApplicationContext()),
|
||||||
|
"Extending native modules with non-matching application contexts.");
|
||||||
|
|
||||||
Map<String, ModuleHolder> newModules = newRegister.getModuleMap();
|
Map<String, ModuleHolder> newModules = newRegister.getModuleMap();
|
||||||
|
|
||||||
|
@ -86,8 +78,7 @@ public class NativeModuleRegistry {
|
||||||
/* package */ void notifyJSInstanceDestroy() {
|
/* package */ void notifyJSInstanceDestroy() {
|
||||||
mReactApplicationContext.assertOnNativeModulesQueueThread();
|
mReactApplicationContext.assertOnNativeModulesQueueThread();
|
||||||
Systrace.beginSection(
|
Systrace.beginSection(
|
||||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
|
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceDestroy");
|
||||||
"NativeModuleRegistry_notifyJSInstanceDestroy");
|
|
||||||
try {
|
try {
|
||||||
for (ModuleHolder module : mModules.values()) {
|
for (ModuleHolder module : mModules.values()) {
|
||||||
module.destroy();
|
module.destroy();
|
||||||
|
@ -98,14 +89,14 @@ public class NativeModuleRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void notifyJSInstanceInitialized() {
|
/* package */ void notifyJSInstanceInitialized() {
|
||||||
mReactApplicationContext.assertOnNativeModulesQueueThread("From version React Native v0.44, " +
|
mReactApplicationContext.assertOnNativeModulesQueueThread(
|
||||||
"native modules are explicitly not initialized on the UI thread. See " +
|
"From version React Native v0.44, "
|
||||||
"https://github.com/facebook/react-native/wiki/Breaking-Changes#d4611211-reactnativeandroidbreaking-move-nativemodule-initialization-off-ui-thread---aaachiuuu " +
|
+ "native modules are explicitly not initialized on the UI thread. See "
|
||||||
" for more details.");
|
+ "https://github.com/facebook/react-native/wiki/Breaking-Changes#d4611211-reactnativeandroidbreaking-move-nativemodule-initialization-off-ui-thread---aaachiuuu "
|
||||||
|
+ " for more details.");
|
||||||
ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_START);
|
ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_START);
|
||||||
Systrace.beginSection(
|
Systrace.beginSection(
|
||||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
|
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceInitialized");
|
||||||
"NativeModuleRegistry_notifyJSInstanceInitialized");
|
|
||||||
try {
|
try {
|
||||||
for (ModuleHolder module : mModules.values()) {
|
for (ModuleHolder module : mModules.values()) {
|
||||||
module.markInitializable();
|
module.markInitializable();
|
||||||
|
@ -118,7 +109,8 @@ public class NativeModuleRegistry {
|
||||||
|
|
||||||
public void onBatchComplete() {
|
public void onBatchComplete() {
|
||||||
// The only native module that uses the onBatchComplete is the UI Manager. Hence, instead of
|
// The only native module that uses the onBatchComplete is the UI Manager. Hence, instead of
|
||||||
// iterating over all the modules for find this one instance, and then calling it, we short-circuit
|
// iterating over all the modules for find this one instance, and then calling it, we
|
||||||
|
// short-circuit
|
||||||
// the search, and simply call OnBatchComplete on the UI Manager.
|
// the search, and simply call OnBatchComplete on the UI Manager.
|
||||||
// With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away
|
// With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away
|
||||||
ModuleHolder moduleHolder = mModules.get("UIManager");
|
ModuleHolder moduleHolder = mModules.get("UIManager");
|
||||||
|
@ -135,10 +127,25 @@ public class NativeModuleRegistry {
|
||||||
public <T extends NativeModule> T getModule(Class<T> moduleInterface) {
|
public <T extends NativeModule> T getModule(Class<T> moduleInterface) {
|
||||||
ReactModule annotation = moduleInterface.getAnnotation(ReactModule.class);
|
ReactModule annotation = moduleInterface.getAnnotation(ReactModule.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
throw new IllegalArgumentException("Could not find @ReactModule annotation in class " + moduleInterface.getName());
|
throw new IllegalArgumentException(
|
||||||
|
"Could not find @ReactModule annotation in class " + moduleInterface.getName());
|
||||||
}
|
}
|
||||||
return (T) Assertions.assertNotNull(
|
return (T)
|
||||||
mModules.get(annotation.name()), annotation.name() + " could not be found. Is it defined in " + moduleInterface.getName()).getModule();
|
Assertions.assertNotNull(
|
||||||
|
mModules.get(annotation.name()),
|
||||||
|
annotation.name()
|
||||||
|
+ " could not be found. Is it defined in "
|
||||||
|
+ moduleInterface.getName())
|
||||||
|
.getModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasModule(String name) {
|
||||||
|
return mModules.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeModule getModule(String name) {
|
||||||
|
return Assertions.assertNotNull(
|
||||||
|
mModules.get(name), "Could not find module with name " + name).getModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<NativeModule> getAllModules() {
|
public List<NativeModule> getAllModules() {
|
||||||
|
|
Loading…
Reference in New Issue