Skip to content

Commit c70861b

Browse files
author
Marek Fořt
committed
WIP: Fabric Android support
1 parent 4cd0ca9 commit c70861b

20 files changed

Lines changed: 623 additions & 118 deletions

fixture/android/app/src/debug/java/com/flatlistpro/ReactNativeFlipper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
2020
import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
2121
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22+
import com.facebook.react.ReactInstanceEventListener;
2223
import com.facebook.react.ReactInstanceManager;
2324
import com.facebook.react.bridge.ReactContext;
2425
import com.facebook.react.modules.network.NetworkingModule;
@@ -51,7 +52,7 @@ public void apply(OkHttpClient.Builder builder) {
5152
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
5253
if (reactContext == null) {
5354
reactInstanceManager.addReactInstanceEventListener(
54-
new ReactInstanceManager.ReactInstanceEventListener() {
55+
new ReactInstanceEventListener() {
5556
@Override
5657
public void onReactContextInitialized(ReactContext reactContext) {
5758
reactInstanceManager.removeReactInstanceEventListener(this);

fixture/android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
<activity
1616
android:name=".MainActivity"
1717
android:label="@string/app_name"
18-
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
18+
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
1919
android:launchMode="singleTask"
20-
android:windowSoftInputMode="adjustResize">
20+
android:windowSoftInputMode="adjustResize"
21+
android:exported="true">
2122
<intent-filter>
2223
<action android:name="android.intent.action.MAIN" />
2324
<category android:name="android.intent.category.LAUNCHER" />

fixture/android/app/src/main/java/com/flatlistpro/MainActivity.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.flatlistpro;
22

33
import com.facebook.react.ReactActivity;
4+
import com.facebook.react.ReactActivityDelegate;
5+
import com.facebook.react.ReactRootView;
46
import android.os.Bundle;
57

68
public class MainActivity extends ReactActivity {
@@ -14,6 +16,27 @@ protected String getMainComponentName() {
1416
return "FlatListPro";
1517
}
1618

19+
/**
20+
* Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
21+
* you can specify the rendered you wish to use (Fabric or the older renderer).
22+
*/
23+
@Override
24+
protected ReactActivityDelegate createReactActivityDelegate() {
25+
return new MainActivityDelegate(this, getMainComponentName());
26+
}
27+
public static class MainActivityDelegate extends ReactActivityDelegate {
28+
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
29+
super(activity, mainComponentName);
30+
}
31+
@Override
32+
protected ReactRootView createRootView() {
33+
ReactRootView reactRootView = new ReactRootView(getContext());
34+
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
35+
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
36+
return reactRootView;
37+
}
38+
}
39+
1740
@Override
1841
protected void onCreate(Bundle savedInstanceState) {
1942
super.onCreate(null);

fixture/android/app/src/main/java/com/flatlistpro/MainApplication.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import com.facebook.react.ReactInstanceManager;
88
import com.facebook.react.ReactNativeHost;
99
import com.facebook.react.ReactPackage;
10+
import com.facebook.react.config.ReactFeatureFlags;
1011
import com.facebook.soloader.SoLoader;
12+
import com.flatlistpro.newarchitecture.MainApplicationReactNativeHost;
1113
import java.lang.reflect.InvocationTargetException;
1214
import java.util.List;
1315

@@ -43,14 +45,23 @@ protected JSIModulePackage getJSIModulePackage() {
4345
}
4446
};
4547

48+
49+
private final ReactNativeHost mNewArchitectureNativeHost = new MainApplicationReactNativeHost(this);
50+
4651
@Override
4752
public ReactNativeHost getReactNativeHost() {
48-
return mReactNativeHost;
53+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
54+
return mNewArchitectureNativeHost;
55+
} else {
56+
return mReactNativeHost;
57+
}
4958
}
5059

5160
@Override
5261
public void onCreate() {
5362
super.onCreate();
63+
// If you opted-in for the New Architecture, we enable the TurboModule system
64+
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
5465
SoLoader.init(this, /* native exopackage */ false);
5566
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
5667
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.flatlistpro.newarchitecture;
2+
import android.app.Application;
3+
import androidx.annotation.NonNull;
4+
import com.facebook.react.PackageList;
5+
import com.facebook.react.ReactInstanceManager;
6+
import com.facebook.react.ReactNativeHost;
7+
import com.facebook.react.ReactPackage;
8+
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
9+
import com.facebook.react.bridge.JSIModulePackage;
10+
import com.facebook.react.bridge.JSIModuleProvider;
11+
import com.facebook.react.bridge.JSIModuleSpec;
12+
import com.facebook.react.bridge.JSIModuleType;
13+
import com.facebook.react.bridge.JavaScriptContextHolder;
14+
import com.facebook.react.bridge.ReactApplicationContext;
15+
import com.facebook.react.bridge.UIManager;
16+
import com.facebook.react.fabric.ComponentFactory;
17+
import com.facebook.react.fabric.CoreComponentsRegistry;
18+
import com.facebook.react.fabric.EmptyReactNativeConfig;
19+
import com.facebook.react.fabric.FabricJSIModuleProvider;
20+
import com.facebook.react.uimanager.ViewManagerRegistry;
21+
import com.flatlistpro.BuildConfig;
22+
import com.flatlistpro.newarchitecture.components.MainComponentsRegistry;
23+
import com.flatlistpro.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
/**
27+
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
28+
* TurboModule delegates and the Fabric Renderer.
29+
*
30+
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
31+
* `newArchEnabled` property). Is ignored otherwise.
32+
*/
33+
public class MainApplicationReactNativeHost extends ReactNativeHost {
34+
public MainApplicationReactNativeHost(Application application) {
35+
super(application);
36+
}
37+
@Override
38+
public boolean getUseDeveloperSupport() {
39+
return BuildConfig.DEBUG;
40+
}
41+
@Override
42+
protected List<ReactPackage> getPackages() {
43+
List<ReactPackage> packages = new PackageList(this).getPackages();
44+
// Packages that cannot be autolinked yet can be added manually here, for example:
45+
// packages.add(new MyReactNativePackage());
46+
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
47+
// packages.add(new TurboReactPackage() { ... });
48+
// If you have custom Fabric Components, their ViewManagers should also be loaded here
49+
// inside a ReactPackage.
50+
return packages;
51+
}
52+
@Override
53+
protected String getJSMainModuleName() {
54+
return "index";
55+
}
56+
@NonNull
57+
@Override
58+
protected ReactPackageTurboModuleManagerDelegate.Builder
59+
getReactPackageTurboModuleManagerDelegateBuilder() {
60+
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
61+
// for the new architecture and to use TurboModules correctly.
62+
return new MainApplicationTurboModuleManagerDelegate.Builder();
63+
}
64+
@Override
65+
protected JSIModulePackage getJSIModulePackage() {
66+
return new JSIModulePackage() {
67+
@Override
68+
public List<JSIModuleSpec> getJSIModules(
69+
final ReactApplicationContext reactApplicationContext,
70+
final JavaScriptContextHolder jsContext) {
71+
final List<JSIModuleSpec> specs = new ArrayList<>();
72+
// Here we provide a new JSIModuleSpec that will be responsible of providing the
73+
// custom Fabric Components.
74+
specs.add(
75+
new JSIModuleSpec() {
76+
@Override
77+
public JSIModuleType getJSIModuleType() {
78+
return JSIModuleType.UIManager;
79+
}
80+
@Override
81+
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
82+
final ComponentFactory componentFactory = new ComponentFactory();
83+
CoreComponentsRegistry.register(componentFactory);
84+
// Here we register a Components Registry.
85+
// The one that is generated with the template contains no components
86+
// and just provides you the one from React Native core.
87+
MainComponentsRegistry.register(componentFactory);
88+
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
89+
ViewManagerRegistry viewManagerRegistry =
90+
new ViewManagerRegistry(
91+
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
92+
return new FabricJSIModuleProvider(
93+
reactApplicationContext,
94+
componentFactory,
95+
new EmptyReactNativeConfig(),
96+
viewManagerRegistry);
97+
}
98+
});
99+
return specs;
100+
}
101+
};
102+
}
103+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.flatlistpro.newarchitecture.components;
2+
import com.facebook.jni.HybridData;
3+
import com.facebook.proguard.annotations.DoNotStrip;
4+
import com.facebook.react.fabric.ComponentFactory;
5+
import com.facebook.soloader.SoLoader;
6+
/**
7+
* Class responsible to load the custom Fabric Components. This class has native methods and needs a
8+
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
9+
* folder for you).
10+
*
11+
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
12+
* `newArchEnabled` property). Is ignored otherwise.
13+
*/
14+
@DoNotStrip
15+
public class MainComponentsRegistry {
16+
static {
17+
SoLoader.loadLibrary("fabricjni");
18+
}
19+
@DoNotStrip private final HybridData mHybridData;
20+
@DoNotStrip
21+
private native HybridData initHybrid(ComponentFactory componentFactory);
22+
@DoNotStrip
23+
private MainComponentsRegistry(ComponentFactory componentFactory) {
24+
mHybridData = initHybrid(componentFactory);
25+
}
26+
@DoNotStrip
27+
public static MainComponentsRegistry register(ComponentFactory componentFactory) {
28+
return new MainComponentsRegistry(componentFactory);
29+
}
30+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.flatlistpro.newarchitecture.modules;
2+
import com.facebook.jni.HybridData;
3+
import com.facebook.react.ReactPackage;
4+
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
5+
import com.facebook.react.bridge.ReactApplicationContext;
6+
import com.facebook.soloader.SoLoader;
7+
import java.util.List;
8+
/**
9+
* Class responsible to load the TurboModules. This class has native methods and needs a
10+
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
11+
* folder for you).
12+
*
13+
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
14+
* `newArchEnabled` property). Is ignored otherwise.
15+
*/
16+
public class MainApplicationTurboModuleManagerDelegate
17+
extends ReactPackageTurboModuleManagerDelegate {
18+
private static volatile boolean sIsSoLibraryLoaded;
19+
protected MainApplicationTurboModuleManagerDelegate(
20+
ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
21+
super(reactApplicationContext, packages);
22+
}
23+
protected native HybridData initHybrid();
24+
native boolean canCreateTurboModule(String moduleName);
25+
public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
26+
protected MainApplicationTurboModuleManagerDelegate build(
27+
ReactApplicationContext context, List<ReactPackage> packages) {
28+
return new MainApplicationTurboModuleManagerDelegate(context, packages);
29+
}
30+
}
31+
@Override
32+
protected synchronized void maybeLoadOtherSoLibraries() {
33+
if (!sIsSoLibraryLoaded) {
34+
// If you change the name of your application .so file in the Android.mk file,
35+
// make sure you update the name here as well.
36+
SoLoader.loadLibrary("rndiffapp_appmodules");
37+
sIsSoLibraryLoaded = true;
38+
}
39+
}
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
THIS_DIR := $(call my-dir)
2+
include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
3+
# If you wish to add a custom TurboModule or Fabric component in your app you
4+
# will have to include the following autogenerated makefile.
5+
# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
6+
include $(CLEAR_VARS)
7+
LOCAL_PATH := $(THIS_DIR)
8+
# You can customize the name of your application .so file here.
9+
LOCAL_MODULE := flatlistpro_appmodules
10+
LOCAL_C_INCLUDES := $(LOCAL_PATH)
11+
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
12+
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
13+
# If you wish to add a custom TurboModule or Fabric component in your app you
14+
# will have to uncomment those lines to include the generated source
15+
# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
16+
#
17+
# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
18+
# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
19+
# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
20+
# Here you should add any native library you wish to depend on.
21+
LOCAL_SHARED_LIBRARIES := \
22+
libfabricjni \
23+
libfbjni \
24+
libfolly_futures \
25+
libfolly_json \
26+
libglog \
27+
libjsi \
28+
libreact_codegen_rncore \
29+
libreact_debug \
30+
libreact_nativemodule_core \
31+
libreact_render_componentregistry \
32+
libreact_render_core \
33+
libreact_render_debug \
34+
libreact_render_graphics \
35+
librrc_view \
36+
libruntimeexecutor \
37+
libturbomodulejsijni \
38+
libyoga
39+
LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall
40+
include $(BUILD_SHARED_LIBRARY)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "MainApplicationModuleProvider.h"
2+
#include <rncore.h>
3+
namespace facebook {
4+
namespace react {
5+
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
6+
const std::string moduleName,
7+
const JavaTurboModule::InitParams &params) {
8+
// Here you can provide your own module provider for TurboModules coming from
9+
// either your application or from external libraries. The approach to follow
10+
// is similar to the following (for a library called `samplelibrary`:
11+
//
12+
// auto module = samplelibrary_ModuleProvider(moduleName, params);
13+
// if (module != nullptr) {
14+
// return module;
15+
// }
16+
// return rncore_ModuleProvider(moduleName, params);
17+
return rncore_ModuleProvider(moduleName, params);
18+
}
19+
} // namespace react
20+
} // namespace facebook
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include <memory>
3+
#include <string>
4+
#include <ReactCommon/JavaTurboModule.h>
5+
namespace facebook {
6+
namespace react {
7+
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
8+
const std::string moduleName,
9+
const JavaTurboModule::InitParams &params);
10+
} // namespace react
11+
} // namespace facebook

0 commit comments

Comments
 (0)