Detangle destroy and create accesses
Differential Revision: D5823786 fbshipit-source-id: d6a6e29b856361a6b1d5ab48397607a844b5ab53
This commit is contained in:
parent
628cbe170b
commit
6334ed2ff3
|
@ -137,13 +137,18 @@ public class ReactInstanceManager {
|
|||
private final DevSupportManager mDevSupportManager;
|
||||
private final boolean mUseDeveloperSupport;
|
||||
private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
|
||||
private final Object mReactContextLock = new Object();
|
||||
private @Nullable volatile ReactContext mCurrentReactContext;
|
||||
private final Context mApplicationContext;
|
||||
private @Nullable @ThreadConfined(UI) DefaultHardwareBackBtnHandler mDefaultBackButtonImpl;
|
||||
private @Nullable Activity mCurrentActivity;
|
||||
private final Collection<ReactInstanceEventListener> mReactInstanceEventListeners =
|
||||
Collections.synchronizedSet(new HashSet<ReactInstanceEventListener>());
|
||||
// Identifies whether the instance manager is or soon will be initialized (on background thread)
|
||||
private volatile boolean mHasStartedCreatingInitialContext = false;
|
||||
// Identifies whether the insance manager destroy function is in process,
|
||||
// while true any spawned create thread should wait for proper clean up before initializing
|
||||
private volatile Boolean mHasStartedDestroying = false;
|
||||
private final UIImplementationProvider mUIImplementationProvider;
|
||||
private final MemoryPressureRouter mMemoryPressureRouter;
|
||||
private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
|
||||
|
@ -473,13 +478,13 @@ public class ReactInstanceManager {
|
|||
public void onBackPressed() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
ReactContext reactContext = mCurrentReactContext;
|
||||
if (mCurrentReactContext == null) {
|
||||
if (reactContext == null) {
|
||||
// Invoke without round trip to JS.
|
||||
FLog.w(ReactConstants.TAG, "Instance detached from instance manager");
|
||||
invokeDefaultOnBackPressed();
|
||||
} else {
|
||||
DeviceEventManagerModule deviceEventManagerModule =
|
||||
Assertions.assertNotNull(reactContext).getNativeModule(DeviceEventManagerModule.class);
|
||||
reactContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
deviceEventManagerModule.emitHardwareBackPressed();
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +502,8 @@ public class ReactInstanceManager {
|
|||
@ThreadConfined(UI)
|
||||
public void onNewIntent(Intent intent) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (mCurrentReactContext == null) {
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext == null) {
|
||||
FLog.w(ReactConstants.TAG, "Instance detached from instance manager");
|
||||
} else {
|
||||
String action = intent.getAction();
|
||||
|
@ -505,18 +511,18 @@ public class ReactInstanceManager {
|
|||
|
||||
if (Intent.ACTION_VIEW.equals(action) && uri != null) {
|
||||
DeviceEventManagerModule deviceEventManagerModule =
|
||||
Assertions.assertNotNull(mCurrentReactContext)
|
||||
.getNativeModule(DeviceEventManagerModule.class);
|
||||
currentContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
deviceEventManagerModule.emitNewIntentReceived(uri);
|
||||
}
|
||||
|
||||
mCurrentReactContext.onNewIntent(mCurrentActivity, intent);
|
||||
currentContext.onNewIntent(mCurrentActivity, intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleElementInspector() {
|
||||
if (mCurrentReactContext != null) {
|
||||
mCurrentReactContext
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
currentContext
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit("toggleElementInspector", null);
|
||||
}
|
||||
|
@ -623,6 +629,8 @@ public class ReactInstanceManager {
|
|||
UiThreadUtil.assertOnUiThread();
|
||||
PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Destroy");
|
||||
|
||||
mHasStartedDestroying = true;
|
||||
|
||||
if (mUseDeveloperSupport) {
|
||||
mDevSupportManager.setDevSupportEnabled(false);
|
||||
mDevSupportManager.stopInspector();
|
||||
|
@ -631,54 +639,62 @@ public class ReactInstanceManager {
|
|||
moveToBeforeCreateLifecycleState();
|
||||
|
||||
if (mCreateReactContextThread != null) {
|
||||
mCreateReactContextThread.interrupt();
|
||||
mCreateReactContextThread = null;
|
||||
}
|
||||
|
||||
mMemoryPressureRouter.destroy(mApplicationContext);
|
||||
|
||||
if (mCurrentReactContext != null) {
|
||||
mCurrentReactContext.destroy();
|
||||
mCurrentReactContext = null;
|
||||
mHasStartedCreatingInitialContext = false;
|
||||
synchronized (mReactContextLock) {
|
||||
if (mCurrentReactContext != null) {
|
||||
mCurrentReactContext.destroy();
|
||||
mCurrentReactContext = null;
|
||||
}
|
||||
}
|
||||
mHasStartedCreatingInitialContext = false;
|
||||
mCurrentActivity = null;
|
||||
|
||||
ResourceDrawableIdHelper.getInstance().clear();
|
||||
mHasStartedDestroying = false;
|
||||
synchronized (mHasStartedDestroying) {
|
||||
mHasStartedDestroying.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void moveToResumedLifecycleState(boolean force) {
|
||||
if (mCurrentReactContext != null) {
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
// we currently don't have an onCreate callback so we call onResume for both transitions
|
||||
if (force ||
|
||||
mLifecycleState == LifecycleState.BEFORE_RESUME ||
|
||||
mLifecycleState == LifecycleState.BEFORE_CREATE) {
|
||||
mCurrentReactContext.onHostResume(mCurrentActivity);
|
||||
currentContext.onHostResume(mCurrentActivity);
|
||||
}
|
||||
}
|
||||
mLifecycleState = LifecycleState.RESUMED;
|
||||
}
|
||||
|
||||
private synchronized void moveToBeforeResumeLifecycleState() {
|
||||
if (mCurrentReactContext != null) {
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
if (mLifecycleState == LifecycleState.BEFORE_CREATE) {
|
||||
mCurrentReactContext.onHostResume(mCurrentActivity);
|
||||
mCurrentReactContext.onHostPause();
|
||||
currentContext.onHostResume(mCurrentActivity);
|
||||
currentContext.onHostPause();
|
||||
} else if (mLifecycleState == LifecycleState.RESUMED) {
|
||||
mCurrentReactContext.onHostPause();
|
||||
currentContext.onHostPause();
|
||||
}
|
||||
}
|
||||
mLifecycleState = LifecycleState.BEFORE_RESUME;
|
||||
}
|
||||
|
||||
private synchronized void moveToBeforeCreateLifecycleState() {
|
||||
if (mCurrentReactContext != null) {
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
if (mLifecycleState == LifecycleState.RESUMED) {
|
||||
mCurrentReactContext.onHostPause();
|
||||
currentContext.onHostPause();
|
||||
mLifecycleState = LifecycleState.BEFORE_RESUME;
|
||||
}
|
||||
if (mLifecycleState == LifecycleState.BEFORE_RESUME) {
|
||||
mCurrentReactContext.onHostDestroy();
|
||||
currentContext.onHostDestroy();
|
||||
}
|
||||
}
|
||||
mLifecycleState = LifecycleState.BEFORE_CREATE;
|
||||
|
@ -692,8 +708,9 @@ public class ReactInstanceManager {
|
|||
|
||||
@ThreadConfined(UI)
|
||||
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
||||
if (mCurrentReactContext != null) {
|
||||
mCurrentReactContext.onActivityResult(activity, requestCode, resultCode, data);
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
currentContext.onActivityResult(activity, requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -722,8 +739,9 @@ public class ReactInstanceManager {
|
|||
|
||||
// If react context is being created in the background, JS application will be started
|
||||
// automatically when creation completes, as root view is part of the attached root view list.
|
||||
if (mCreateReactContextThread == null && mCurrentReactContext != null) {
|
||||
attachRootViewToInstance(rootView, mCurrentReactContext.getCatalystInstance());
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (mCreateReactContextThread == null && currentContext != null) {
|
||||
attachRootViewToInstance(rootView, currentContext.getCatalystInstance());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -736,8 +754,9 @@ public class ReactInstanceManager {
|
|||
public void detachRootView(ReactRootView rootView) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (mAttachedRootViews.remove(rootView)) {
|
||||
if (mCurrentReactContext != null && mCurrentReactContext.hasActiveCatalystInstance()) {
|
||||
detachViewFromInstance(rootView, mCurrentReactContext.getCatalystInstance());
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null && currentContext.hasActiveCatalystInstance()) {
|
||||
detachViewFromInstance(rootView, currentContext.getCatalystInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -777,7 +796,9 @@ public class ReactInstanceManager {
|
|||
|
||||
@VisibleForTesting
|
||||
public @Nullable ReactContext getCurrentReactContext() {
|
||||
return mCurrentReactContext;
|
||||
synchronized (mReactContextLock) {
|
||||
return mCurrentReactContext;
|
||||
}
|
||||
}
|
||||
|
||||
public LifecycleState getLifecycleState() {
|
||||
|
@ -828,14 +849,28 @@ public class ReactInstanceManager {
|
|||
private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.runCreateReactContextOnNewThread()");
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (mCurrentReactContext != null) {
|
||||
tearDownReactContext(mCurrentReactContext);
|
||||
mCurrentReactContext = null;
|
||||
synchronized (mReactContextLock) {
|
||||
if (mCurrentReactContext != null) {
|
||||
tearDownReactContext(mCurrentReactContext);
|
||||
mCurrentReactContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
mCreateReactContextThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (ReactInstanceManager.this.mHasStartedDestroying) {
|
||||
while (ReactInstanceManager.this.mHasStartedDestroying) {
|
||||
try {
|
||||
ReactInstanceManager.this.mHasStartedDestroying.wait();
|
||||
} catch (InterruptedException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// As destroy() may have run and set this to false, ensure that it is true before we create
|
||||
mHasStartedCreatingInitialContext = true;
|
||||
|
||||
try {
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
|
||||
final ReactApplicationContext reactApplicationContext = createReactContext(
|
||||
|
@ -879,7 +914,9 @@ public class ReactInstanceManager {
|
|||
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_END);
|
||||
ReactMarker.logMarker(SETUP_REACT_CONTEXT_START);
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "setupReactContext");
|
||||
mCurrentReactContext = Assertions.assertNotNull(reactContext);
|
||||
synchronized (mReactContextLock) {
|
||||
mCurrentReactContext = Assertions.assertNotNull(reactContext);
|
||||
}
|
||||
CatalystInstance catalystInstance =
|
||||
Assertions.assertNotNull(reactContext.getCatalystInstance());
|
||||
|
||||
|
|
Loading…
Reference in New Issue