Summary:
We currently have two different codepaths for actually rendering a surface with Fabric on iOS and Android: on iOS we use Fabric's `UIManagerBinding.startSurface` to call `AppRegistry.runApplication`, but on Android we don't; instead we use the same codepath as paper, calling `ReactRootView.runApplication`.

This diff does a few different things:
1. Unify iOS and Android by removing the `#ifndef` for Android so that we call `startSurface` for both
2. Pass through the JS module name on Android so that this actually works (it currently passes in an empty string)
3. Remove the call to `ReactRootView.runApplication` for Fabric so that we don't end up doing this twice
4. Copy over some logic that we need from `ReactRootView.runApplication` (make sure that root layout specs get updated, and that content appeared gets logged)

Reviewed By: mdvacca

Differential Revision: D15501666

fbshipit-source-id: 5c96c8cf036261cb99729b1dbdff0f7c09a32d76
This commit is contained in:
Emily Janzer 2019-05-28 12:14:36 -07:00 коммит произвёл Facebook Github Bot
Родитель ab1a42762c
Коммит 298f59c5d3
8 изменённых файлов: 62 добавлений и 24 удалений

Просмотреть файл

@ -1050,16 +1050,24 @@ public class ReactInstanceManager {
private void attachRootViewToInstance(final ReactRoot reactRoot) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
UIManager uiManagerModule = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
UIManager uiManager = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
@Nullable Bundle initialProperties = reactRoot.getAppProperties();
final int rootTag = uiManagerModule.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null ?
final int rootTag = uiManager.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null ?
new WritableNativeMap() : Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate());
reactRoot.setRootViewTag(rootTag);
reactRoot.runApplication();
if (reactRoot.getUIManagerType() == FABRIC) {
// Fabric requires to call updateRootLayoutSpecs before starting JS Application,
// this ensures the root will hace the correct pointScaleFactor.
uiManager.updateRootLayoutSpecs(rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
reactRoot.setShouldLogContentAppeared(true);
} else {
reactRoot.runApplication();
}
Systrace.beginAsyncSection(
TRACE_TAG_REACT_JAVA_BRIDGE,
"pre_rootView.onAttachedToReactInstance",

Просмотреть файл

@ -405,6 +405,21 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
}
}
@Override
public int getWidthMeasureSpec() {
return mWidthMeasureSpec;
}
@Override
public int getHeightMeasureSpec() {
return mHeightMeasureSpec;
}
@Override
public void setShouldLogContentAppeared(boolean shouldLogContentAppeared) {
mShouldLogContentAppeared = shouldLogContentAppeared;
}
private void updateRootLayoutSpecs(final int widthMeasureSpec, final int heightMeasureSpec) {
if (mReactInstanceManager == null) {
FLog.w(
@ -461,7 +476,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
mRootViewEventListener = eventListener;
}
/* package */ String getJSModuleName() {
@Override
public String getJSModuleName() {
return Assertions.assertNotNull(mJSModuleName);
}
@ -506,11 +522,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
if (mUseSurface) {
// TODO call surface's runApplication
} else {
boolean isFabric = getUIManagerType() == FABRIC;
// Fabric requires to call updateRootLayoutSpecs before starting JS Application,
// this ensures the root will hace the correct pointScaleFactor.
if (mWasMeasured || isFabric) {
if (mWasMeasured) {
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
}
@ -520,9 +532,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
}
if (isFabric) {
appParams.putBoolean("fabric", true);
}
mShouldLogContentAppeared = true;

Просмотреть файл

@ -39,7 +39,7 @@ public class Binding {
ComponentFactoryDelegate componentsRegistry,
Object reactNativeConfig);
public native void startSurface(int surfaceId, NativeMap initialProps);
public native void startSurface(int surfaceId, String moduleName, NativeMap initialProps);
public native void renderTemplateToSurface(int surfaceId, String uiTemplate);

Просмотреть файл

@ -53,6 +53,7 @@ import com.facebook.react.fabric.mounting.mountitems.UpdateLocalDataMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.ReactRoot;
import com.facebook.react.uimanager.ReactRootViewTagGenerator;
import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext;
@ -127,13 +128,18 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@Override
public <T extends View> int addRootView(
final T rootView, final WritableMap initialProps, final @Nullable String initialUITemplate) {
final T rootView, final WritableMap initialProps, final @Nullable String initialUITemplate) {
return addRootView(rootView, ((ReactRoot) rootView).getJSModuleName(), initialProps, initialUITemplate);
}
public <T extends View> int addRootView(
final T rootView, final String moduleName, final WritableMap initialProps, final @Nullable String initialUITemplate) {
final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag();
ThemedReactContext reactContext =
new ThemedReactContext(mReactApplicationContext, rootView.getContext());
mMountingManager.addRootView(rootTag, rootView);
mReactContextForRootTag.put(rootTag, reactContext);
mBinding.startSurface(rootTag, (NativeMap) initialProps);
mBinding.startSurface(rootTag, moduleName, (NativeMap) initialProps);
if (initialUITemplate != null) {
mBinding.renderTemplateToSurface(rootTag, initialUITemplate);
}

Просмотреть файл

@ -45,9 +45,13 @@ jni::local_ref<Binding::jhybriddata> Binding::initHybrid(
return makeCxxInstance();
}
void Binding::startSurface(jint surfaceId, NativeMap *initialProps) {
void Binding::startSurface(
jint surfaceId,
jni::alias_ref<jstring> moduleName,
NativeMap *initialProps) {
if (scheduler_) {
scheduler_->startSurface(surfaceId, "", initialProps->consume());
scheduler_->startSurface(
surfaceId, moduleName->toStdString(), initialProps->consume());
}
}

Просмотреть файл

@ -50,7 +50,10 @@ class Binding : public jni::HybridClass<Binding>, public SchedulerDelegate {
ComponentFactoryDelegate *componentsRegistry,
jni::alias_ref<jobject> reactNativeConfig);
void startSurface(jint surfaceId, NativeMap *initialProps);
void startSurface(
jint surfaceId,
jni::alias_ref<jstring> moduleName,
NativeMap *initialProps);
void renderTemplateToSurface(jint surfaceId, jstring uiTemplate);

Просмотреть файл

@ -23,6 +23,7 @@ public interface ReactRoot {
*/
@Nullable Bundle getAppProperties();
@Nullable String getInitialUITemplate();
String getJSModuleName();
/**
* Fabric or Default UI Manager, see {@link UIManagerType}
@ -47,4 +48,15 @@ public interface ReactRoot {
* Return native view for root
*/
ViewGroup getRootViewGroup();
/**
* @return Cached values for widthMeasureSpec and heightMeasureSpec
*/
int getWidthMeasureSpec();
int getHeightMeasureSpec();
/**
* Sets a flag that determines whether to log that content appeared on next view added.
*/
void setShouldLogContentAppeared(boolean shouldLogContentAppeared);
}

Просмотреть файл

@ -96,12 +96,10 @@ void Scheduler::startSurface(
shadowTreeRegistry_.add(std::move(shadowTree));
#ifndef ANDROID
runtimeExecutor_([=](jsi::Runtime &runtime) {
uiManagerBinding_->startSurface(
runtime, surfaceId, moduleName, initialProps);
});
#endif
}
void Scheduler::renderTemplateToSurface(
@ -171,11 +169,9 @@ void Scheduler::stopSurface(SurfaceId surfaceId) const {
auto shadowTree = shadowTreeRegistry_.remove(surfaceId);
shadowTree->setDelegate(nullptr);
#ifndef ANDROID
runtimeExecutor_([=](jsi::Runtime &runtime) {
uiManagerBinding_->stopSurface(runtime, surfaceId);
});
#endif
}
Size Scheduler::measureSurface(