-
Notifications
You must be signed in to change notification settings - Fork 24.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce BaseReactPackage class (#40775)
Summary: Pull Request resolved: #40775 In this diff I'm introducing the BaseReactPackage class to the public API of React Native Android. the goal is for this class to replace TurboReactPackage, which will be Deprecated in the New Architecture changelog: [internal] internal Reviewed By: christophpurrer Differential Revision: D50128456 fbshipit-source-id: a65e1eb0d81b94e442799226784f73f489eabb73
- Loading branch information
1 parent
7b7f128
commit 7a31ecd
Showing
2 changed files
with
162 additions
and
148 deletions.
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
packages/react-native/ReactAndroid/src/main/java/com/facebook/react/BaseReactPackage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.facebook.react; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
import com.facebook.react.bridge.ModuleHolder; | ||
import com.facebook.react.bridge.ModuleSpec; | ||
import com.facebook.react.bridge.NativeModule; | ||
import com.facebook.react.bridge.ReactApplicationContext; | ||
import com.facebook.react.config.ReactFeatureFlags; | ||
import com.facebook.react.module.model.ReactModuleInfo; | ||
import com.facebook.react.module.model.ReactModuleInfoProvider; | ||
import com.facebook.react.uimanager.ViewManager; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
import java.util.Set; | ||
import javax.inject.Provider; | ||
|
||
/** Abstract class that supports lazy loading of NativeModules by default. */ | ||
public abstract class BaseReactPackage implements ReactPackage { | ||
|
||
@Override | ||
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) { | ||
throw new UnsupportedOperationException( | ||
"createNativeModules method is not supported. Use getModule() method instead."); | ||
} | ||
|
||
/** | ||
* The API needed for TurboModules. Given a module name, it returns an instance of {@link | ||
* NativeModule} for the name | ||
* | ||
* @param name name of the Native Module | ||
* @param reactContext {@link ReactApplicationContext} context for this | ||
*/ | ||
@Override | ||
public abstract @Nullable NativeModule getModule( | ||
@NonNull String name, @NonNull ReactApplicationContext reactContext); | ||
|
||
/** | ||
* This is a temporary method till we implement TurboModules. Once we implement TurboModules, we | ||
* will be able to directly call {@link BaseReactPackage#getModule(String, | ||
* ReactApplicationContext)} This method will be removed when TurboModule implementation is | ||
* complete | ||
* | ||
* @param reactContext | ||
* @return | ||
*/ | ||
/** package */ | ||
Iterable<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) { | ||
final Set<Map.Entry<String, ReactModuleInfo>> entrySet = | ||
getReactModuleInfoProvider().getReactModuleInfos().entrySet(); | ||
final Iterator<Map.Entry<String, ReactModuleInfo>> entrySetIterator = entrySet.iterator(); | ||
// This should ideally be an IteratorConvertor, but we don't have any internal library for it | ||
return () -> | ||
new Iterator<ModuleHolder>() { | ||
@Nullable Map.Entry<String, ReactModuleInfo> nextEntry = null; | ||
|
||
private void findNext() { | ||
while (entrySetIterator.hasNext()) { | ||
Map.Entry<String, ReactModuleInfo> entry = entrySetIterator.next(); | ||
ReactModuleInfo reactModuleInfo = entry.getValue(); | ||
|
||
// This Iterator is used to create the NativeModule registry. The NativeModule | ||
// registry must not have TurboModules. Therefore, if TurboModules are enabled, and | ||
// the current NativeModule is a TurboModule, we need to skip iterating over it. | ||
if (ReactFeatureFlags.useTurboModules && reactModuleInfo.isTurboModule()) { | ||
continue; | ||
} | ||
|
||
nextEntry = entry; | ||
return; | ||
} | ||
nextEntry = null; | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
if (nextEntry == null) { | ||
findNext(); | ||
} | ||
return nextEntry != null; | ||
} | ||
|
||
@Override | ||
public ModuleHolder next() { | ||
if (nextEntry == null) { | ||
findNext(); | ||
} | ||
|
||
if (nextEntry == null) { | ||
throw new NoSuchElementException("ModuleHolder not found"); | ||
} | ||
|
||
Map.Entry<String, ReactModuleInfo> entry = nextEntry; | ||
|
||
// Advance iterator | ||
findNext(); | ||
String name = entry.getKey(); | ||
ReactModuleInfo reactModuleInfo = entry.getValue(); | ||
return new ModuleHolder(reactModuleInfo, new ModuleHolderProvider(name, reactContext)); | ||
} | ||
|
||
@Override | ||
public void remove() { | ||
throw new UnsupportedOperationException("Cannot remove native modules from the list"); | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* @param reactContext react application context that can be used to create View Managers. | ||
* @return list of module specs that can create the View Managers. | ||
*/ | ||
protected List<ModuleSpec> getViewManagers(ReactApplicationContext reactContext) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
@Override | ||
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) { | ||
List<ModuleSpec> viewManagerModuleSpecs = getViewManagers(reactContext); | ||
if (viewManagerModuleSpecs == null || viewManagerModuleSpecs.isEmpty()) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
List<ViewManager> viewManagers = new ArrayList<>(); | ||
for (ModuleSpec moduleSpec : viewManagerModuleSpecs) { | ||
viewManagers.add((ViewManager) moduleSpec.getProvider().get()); | ||
} | ||
return viewManagers; | ||
} | ||
|
||
public abstract ReactModuleInfoProvider getReactModuleInfoProvider(); | ||
|
||
private class ModuleHolderProvider implements Provider<NativeModule> { | ||
|
||
private final String mName; | ||
private final ReactApplicationContext mReactContext; | ||
|
||
public ModuleHolderProvider(String name, ReactApplicationContext reactContext) { | ||
mName = name; | ||
mReactContext = reactContext; | ||
} | ||
|
||
@Override | ||
public @Nullable NativeModule get() { | ||
return getModule(mName, mReactContext); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters