Files
react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java
T
David VaccaandFacebook GitHub Bot 74a756846f Fix race condition on startSurface
Summary:
The root cause of this bug is a race condition between the onMeasure method and setupReactContext.

ReactInstanceManager.attachRootView() method is responsible of the initialization of ReactRootViews and it is invoked by ReactRootView.onMeasure() method in the UIThread

Important initialization steps:
1. Clear the Id of the ReactRootView
2. Add the ReactRootView to the mAttachedReactRoots
3. Call StartSurface (if the bridge has been initialized)

Sometimes, when this method is invoked for the first time, the bridge is not initialized, in those cases we delay the start of the surface.

Once the bridge is initialized, StartSurface is called by the setupReactContext() running in the NativeModuleThread.

Since onMeasure can be called multiple times, it is possible that we call "StartSurface" twice for the same ReactRootView, causing the bug reported on T78832286.

This diff adds an extra check to prevent calling "StartSurface" twice. The fix is done using an AtomicInteger comparison and it is gated by the flag "enableStartSurfaceRaceConditionFix". Once we verify this works fine in production we will clean up the code, remove the flags and maybe revisit the API of ReactRoot.

changelog: [Android] Fix race-condition on the initialization of ReactRootViews

Reviewed By: JoshuaGross

Differential Revision: D25255877

fbshipit-source-id: ca8fb00f50e86891fb4c5a06240177cc1a0186d9
2020-12-04 19:58:10 -08:00

76 lines
2.2 KiB
Java

/*
* Copyright (c) Facebook, Inc. and its 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.uimanager;
import android.os.Bundle;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.common.UIManagerType;
import java.util.concurrent.atomic.AtomicInteger;
/** Interface for the root native view of a React native application */
public interface ReactRoot {
/** This constant represents that ReactRoot hasn't started yet or it has been destroyed. */
int STATE_STOPPED = 0;
/** This constant represents that ReactRoot has started. */
int STATE_STARTED = 1;
/** Return cached launch properties for app */
@Nullable
Bundle getAppProperties();
@Nullable
String getInitialUITemplate();
String getJSModuleName();
/** Fabric or Default UI Manager, see {@link UIManagerType} */
@UIManagerType
int getUIManagerType();
int getRootViewTag();
void setRootViewTag(int rootViewTag);
/** Calls into JS to start the React application. */
void runApplication();
/** Handler for stages {@link com.facebook.react.surface.ReactStage} */
void onStage(int stage);
/** Return native view for root */
ViewGroup getRootViewGroup();
/** @return Cached values for widthMeasureSpec. */
int getWidthMeasureSpec();
/** @return Cached values for and heightMeasureSpec. */
int getHeightMeasureSpec();
/** Sets a flag that determines whether to log that content appeared on next view added. */
void setShouldLogContentAppeared(boolean shouldLogContentAppeared);
/**
* @return a {@link String} that represents the root js application that is being rendered with
* this {@link ReactRoot}
* @deprecated We recommend to not use this method as it is will be replaced in the near future.
*/
@Deprecated
@Nullable
String getSurfaceID();
/**
* This API is likely to change once the fix of T78832286 is confirmed TODO: T78832286 revisit
* this API
*
* @return an {@link AtomicInteger} that represents the state of the ReactRoot object. WARNING:
*/
AtomicInteger getState();
}