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) { private void attachRootViewToInstance(final ReactRoot reactRoot) {
Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()"); Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "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(); @Nullable Bundle initialProperties = reactRoot.getAppProperties();
final int rootTag = uiManagerModule.addRootView(
reactRoot.getRootViewGroup(), final int rootTag = uiManager.addRootView(
initialProperties == null ? reactRoot.getRootViewGroup(),
initialProperties == null ?
new WritableNativeMap() : Arguments.fromBundle(initialProperties), new WritableNativeMap() : Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate()); reactRoot.getInitialUITemplate());
reactRoot.setRootViewTag(rootTag); 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( Systrace.beginAsyncSection(
TRACE_TAG_REACT_JAVA_BRIDGE, TRACE_TAG_REACT_JAVA_BRIDGE,
"pre_rootView.onAttachedToReactInstance", "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) { private void updateRootLayoutSpecs(final int widthMeasureSpec, final int heightMeasureSpec) {
if (mReactInstanceManager == null) { if (mReactInstanceManager == null) {
FLog.w( FLog.w(
@ -461,7 +476,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
mRootViewEventListener = eventListener; mRootViewEventListener = eventListener;
} }
/* package */ String getJSModuleName() { @Override
public String getJSModuleName() {
return Assertions.assertNotNull(mJSModuleName); return Assertions.assertNotNull(mJSModuleName);
} }
@ -506,11 +522,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
if (mUseSurface) { if (mUseSurface) {
// TODO call surface's runApplication // TODO call surface's runApplication
} else { } else {
if (mWasMeasured) {
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) {
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec); updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
} }
@ -520,9 +532,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
if (appProperties != null) { if (appProperties != null) {
appParams.putMap("initialProps", Arguments.fromBundle(appProperties)); appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
} }
if (isFabric) {
appParams.putBoolean("fabric", true);
}
mShouldLogContentAppeared = true; mShouldLogContentAppeared = true;

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

@ -39,7 +39,7 @@ public class Binding {
ComponentFactoryDelegate componentsRegistry, ComponentFactoryDelegate componentsRegistry,
Object reactNativeConfig); 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); 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.UpdatePropsMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem;
import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.ReactRoot;
import com.facebook.react.uimanager.ReactRootViewTagGenerator; import com.facebook.react.uimanager.ReactRootViewTagGenerator;
import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
@ -127,13 +128,18 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@Override @Override
public <T extends View> int addRootView( 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(); final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag();
ThemedReactContext reactContext = ThemedReactContext reactContext =
new ThemedReactContext(mReactApplicationContext, rootView.getContext()); new ThemedReactContext(mReactApplicationContext, rootView.getContext());
mMountingManager.addRootView(rootTag, rootView); mMountingManager.addRootView(rootTag, rootView);
mReactContextForRootTag.put(rootTag, reactContext); mReactContextForRootTag.put(rootTag, reactContext);
mBinding.startSurface(rootTag, (NativeMap) initialProps); mBinding.startSurface(rootTag, moduleName, (NativeMap) initialProps);
if (initialUITemplate != null) { if (initialUITemplate != null) {
mBinding.renderTemplateToSurface(rootTag, initialUITemplate); mBinding.renderTemplateToSurface(rootTag, initialUITemplate);
} }

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

@ -45,9 +45,13 @@ jni::local_ref<Binding::jhybriddata> Binding::initHybrid(
return makeCxxInstance(); return makeCxxInstance();
} }
void Binding::startSurface(jint surfaceId, NativeMap *initialProps) { void Binding::startSurface(
jint surfaceId,
jni::alias_ref<jstring> moduleName,
NativeMap *initialProps) {
if (scheduler_) { 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, ComponentFactoryDelegate *componentsRegistry,
jni::alias_ref<jobject> reactNativeConfig); 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); void renderTemplateToSurface(jint surfaceId, jstring uiTemplate);

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

@ -23,6 +23,7 @@ public interface ReactRoot {
*/ */
@Nullable Bundle getAppProperties(); @Nullable Bundle getAppProperties();
@Nullable String getInitialUITemplate(); @Nullable String getInitialUITemplate();
String getJSModuleName();
/** /**
* Fabric or Default UI Manager, see {@link UIManagerType} * Fabric or Default UI Manager, see {@link UIManagerType}
@ -47,4 +48,15 @@ public interface ReactRoot {
* Return native view for root * Return native view for root
*/ */
ViewGroup getRootViewGroup(); 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)); shadowTreeRegistry_.add(std::move(shadowTree));
#ifndef ANDROID
runtimeExecutor_([=](jsi::Runtime &runtime) { runtimeExecutor_([=](jsi::Runtime &runtime) {
uiManagerBinding_->startSurface( uiManagerBinding_->startSurface(
runtime, surfaceId, moduleName, initialProps); runtime, surfaceId, moduleName, initialProps);
}); });
#endif
} }
void Scheduler::renderTemplateToSurface( void Scheduler::renderTemplateToSurface(
@ -171,11 +169,9 @@ void Scheduler::stopSurface(SurfaceId surfaceId) const {
auto shadowTree = shadowTreeRegistry_.remove(surfaceId); auto shadowTree = shadowTreeRegistry_.remove(surfaceId);
shadowTree->setDelegate(nullptr); shadowTree->setDelegate(nullptr);
#ifndef ANDROID
runtimeExecutor_([=](jsi::Runtime &runtime) { runtimeExecutor_([=](jsi::Runtime &runtime) {
uiManagerBinding_->stopSurface(runtime, surfaceId); uiManagerBinding_->stopSurface(runtime, surfaceId);
}); });
#endif
} }
Size Scheduler::measureSurface( Size Scheduler::measureSurface(