use a static react instance holder

Reviewed By: astreet

Differential Revision: D2937867

fb-gh-sync-id: cdda79929fa5993b6ef159aa73922909017c2ded
shipit-source-id: cdda79929fa5993b6ef159aa73922909017c2ded
This commit is contained in:
Felix Oghina
2016-02-19 05:06:15 -08:00
committed by facebook-github-bot-7
parent b516976457
commit 19a1c4c229
7 changed files with 124 additions and 47 deletions

View File

@@ -75,7 +75,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
overridePendingTransition(0, 0);
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
mReactInstanceManager.onHostPause();
}
}
@@ -86,7 +86,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
mLifecycleState = LifecycleState.RESUMED;
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this, this);
mReactInstanceManager.onHostResume(this, this);
}
}
@@ -96,7 +96,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
mDestroyCountDownLatch.countDown();
if (mReactInstanceManager != null) {
mReactInstanceManager.onDestroy();
mReactInstanceManager.destroy();
}
}
@@ -114,7 +114,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
public void resetRootViewForScreenshotTests() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onDestroy();
mReactInstanceManager.destroy();
mReactInstanceManager = null;
}
mReactRootView = new ReactRootView(this);
@@ -148,7 +148,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
.setInitialLifecycleState(mLifecycleState);
mReactInstanceManager = builder.build();
mReactInstanceManager.onResume(this, this);
mReactInstanceManager.onHostResume(this, this);
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {

View File

@@ -74,7 +74,7 @@ public abstract class ReactIntegrationTestCase extends AndroidTestCase {
@Override
public void run() {
if (contextToDestroy != null) {
contextToDestroy.onDestroy();
contextToDestroy.destroy();
}
}
});

View File

@@ -21,7 +21,7 @@ package com.facebook.react;
* RESUMED
*/
public enum LifecycleState {
BEFORE_CREATE,
BEFORE_RESUME,
RESUMED,
}

View File

@@ -150,7 +150,7 @@ public abstract class ReactActivity extends Activity implements DefaultHardwareB
mLifecycleState = LifecycleState.BEFORE_RESUME;
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
mReactInstanceManager.onHostPause();
}
}
@@ -161,7 +161,7 @@ public abstract class ReactActivity extends Activity implements DefaultHardwareB
mLifecycleState = LifecycleState.RESUMED;
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this, this);
mReactInstanceManager.onHostResume(this, this);
}
}
@@ -170,7 +170,7 @@ public abstract class ReactActivity extends Activity implements DefaultHardwareB
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onDestroy();
mReactInstanceManager.destroy();
}
}

View File

@@ -41,8 +41,8 @@ import com.facebook.react.uimanager.ViewManager;
* The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the activity
* that owns the {@link ReactRootView} that is used to render react application using this
* instance manager (see {@link ReactRootView#startReactApplication}). It's required to pass
* owning activity's lifecycle events to the instance manager (see {@link #onPause},
* {@link #onDestroy} and {@link #onResume}).
* owning activity's lifecycle events to the instance manager (see {@link #onHostPause},
* {@link #onHostDestroy} and {@link #onHostResume}).
*
* Ideally, this would be an interface, but because of the API used by earlier versions, it has to
* have a static method, and so cannot (in Java < 8), be one.
@@ -84,22 +84,32 @@ public abstract class ReactInstanceManager {
* consume the event, mDefaultBackButtonImpl will be invoked at the end of the round trip to JS.
*/
public abstract void onBackPressed();
public abstract void onPause();
/**
* Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do
* any necessary cleanup.
*/
public abstract void onHostPause();
/**
* Use this method when the activity resumes to enable invoking the back button directly from JS.
*
* This method retains an instance to provided mDefaultBackButtonImpl. Thus it's
* important to pass from the activity instance that owns this particular instance of {@link
* ReactInstanceManager}, so that once this instance receive {@link #onDestroy} event it will
* ReactInstanceManager}, so that once this instance receive {@link #onHostDestroy} event it will
* clear the reference to that defaultBackButtonImpl.
*
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
* this instance of {@link ReactInstanceManager}.
*/
public abstract void onResume(
public abstract void onHostResume(
Activity activity,
DefaultHardwareBackBtnHandler defaultBackButtonImpl);
public abstract void onDestroy();
/**
* Call this from {@link Activity#onDestroy()}. This notifies any listening modules so they can do
* any necessary cleanup.
*/
public abstract void onHostDestroy();
public abstract void onActivityResult(int requestCode, int resultCode, Intent data);
public abstract void showDevOptionsDialog();
@@ -125,6 +135,11 @@ public abstract class ReactInstanceManager {
*/
public abstract void detachRootView(ReactRootView rootView);
/**
* Destroy this React instance and the attached JS context.
*/
public abstract void destroy();
/**
* Uses configured {@link ReactPackage} instances to create all view managers
*/

View File

@@ -18,8 +18,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import android.app.Activity;
import android.app.Application;
@@ -73,7 +71,18 @@ import com.facebook.react.uimanager.ViewManager;
import com.facebook.soloader.SoLoader;
import com.facebook.systrace.Systrace;
import static com.facebook.react.bridge.ReactMarkerConstants.*;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_JS_MODULE_CONFIG_END;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_JS_MODULE_CONFIG_START;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_REACT_CONTEXT_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_REACT_CONTEXT_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_PACKAGES_END;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_PACKAGES_START;
import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START;
/**
* This class is managing instances of {@link CatalystInstance}. It expose a way to configure
@@ -87,8 +96,8 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
* The lifecycle of the instance of {@link ReactInstanceManagerImpl} should be bound to the activity
* that owns the {@link ReactRootView} that is used to render react application using this
* instance manager (see {@link ReactRootView#startReactApplication}). It's required to pass
* owning activity's lifecycle events to the instance manager (see {@link #onPause},
* {@link #onDestroy} and {@link #onResume}).
* owning activity's lifecycle events to the instance manager (see {@link #onHostPause},
* {@link #onHostDestroy} and {@link #onHostResume}).
*
* To instantiate an instance of this class use {@link #builder}.
*/
@@ -458,20 +467,16 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
}
@Override
public void onPause() {
public void onHostPause() {
UiThreadUtil.assertOnUiThread();
mLifecycleState = LifecycleState.BEFORE_RESUME;
mDefaultBackButtonImpl = null;
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
moveToBeforeResumeLifecycleState();
mCurrentActivity = null;
if (mCurrentReactContext != null) {
mCurrentReactContext.onPause();
}
}
/**
@@ -479,17 +484,16 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
*
* This method retains an instance to provided mDefaultBackButtonImpl. Thus it's
* important to pass from the activity instance that owns this particular instance of {@link
* ReactInstanceManagerImpl}, so that once this instance receive {@link #onDestroy} event it will
* ReactInstanceManagerImpl}, so that once this instance receive {@link #onHostDestroy} event it will
* clear the reference to that defaultBackButtonImpl.
*
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
* this instance of {@link ReactInstanceManagerImpl}.
*/
@Override
public void onResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
UiThreadUtil.assertOnUiThread();
mLifecycleState = LifecycleState.RESUMED;
mDefaultBackButtonImpl = defaultBackButtonImpl;
if (mUseDeveloperSupport) {
@@ -497,32 +501,82 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
}
mCurrentActivity = activity;
if (mCurrentReactContext != null) {
mCurrentReactContext.onResume(activity);
}
moveToResumedLifecycleState(false);
}
@Override
public void onDestroy() {
public void onHostDestroy() {
UiThreadUtil.assertOnUiThread();
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
moveToBeforeCreateLifecycleState();
mCurrentActivity = null;
}
@Override
public void destroy() {
UiThreadUtil.assertOnUiThread();
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
moveToBeforeCreateLifecycleState();
if (mReactContextInitAsyncTask != null) {
mReactContextInitAsyncTask.cancel(true);
}
mMemoryPressureRouter.destroy(mApplicationContext);
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
if (mCurrentReactContext != null) {
mCurrentReactContext.onDestroy();
mCurrentReactContext.destroy();
mCurrentReactContext = null;
mHasStartedCreatingInitialContext = false;
}
mCurrentActivity = null;
}
private void moveToResumedLifecycleState(boolean force) {
if (mCurrentReactContext != 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);
}
}
mLifecycleState = LifecycleState.RESUMED;
}
private void moveToBeforeResumeLifecycleState() {
if (mCurrentReactContext != null) {
if (mLifecycleState == LifecycleState.BEFORE_CREATE) {
mCurrentReactContext.onHostResume(mCurrentActivity);
mCurrentReactContext.onHostPause();
} else if (mLifecycleState == LifecycleState.RESUMED) {
mCurrentReactContext.onHostPause();
}
}
mLifecycleState = LifecycleState.BEFORE_RESUME;
}
private void moveToBeforeCreateLifecycleState() {
if (mCurrentReactContext != null) {
if (mLifecycleState == LifecycleState.RESUMED) {
mCurrentReactContext.onHostPause();
mLifecycleState = LifecycleState.BEFORE_RESUME;
}
if (mLifecycleState == LifecycleState.BEFORE_RESUME) {
mCurrentReactContext.onHostDestroy();
}
}
mLifecycleState = LifecycleState.BEFORE_CREATE;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mCurrentReactContext != null) {
@@ -657,7 +711,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
catalystInstance.initialize();
mDevSupportManager.onNewReactContextCreated(reactContext);
mMemoryPressureRouter.onNewReactContextCreated(reactContext);
moveReactContextToCurrentLifecycleState(reactContext);
moveReactContextToCurrentLifecycleState();
for (ReactRootView rootView : mAttachedRootViews) {
attachMeasuredRootViewToInstance(rootView, catalystInstance);
@@ -706,12 +760,12 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
private void tearDownReactContext(ReactContext reactContext) {
UiThreadUtil.assertOnUiThread();
if (mLifecycleState == LifecycleState.RESUMED) {
reactContext.onPause();
reactContext.onHostPause();
}
for (ReactRootView rootView : mAttachedRootViews) {
detachViewFromInstance(rootView, reactContext.getCatalystInstance());
}
reactContext.onDestroy();
reactContext.destroy();
mDevSupportManager.onReactInstanceDestroyed(reactContext);
mMemoryPressureRouter.onReactInstanceDestroyed();
}
@@ -831,9 +885,9 @@ import static com.facebook.react.bridge.ReactMarkerConstants.*;
}
}
private void moveReactContextToCurrentLifecycleState(ReactApplicationContext reactContext) {
private void moveReactContextToCurrentLifecycleState() {
if (mLifecycleState == LifecycleState.RESUMED) {
reactContext.onResume(mCurrentActivity);
moveToResumedLifecycleState(true);
}
}
}

View File

@@ -133,7 +133,7 @@ public class ReactContext extends ContextWrapper {
/**
* Should be called by the hosting Fragment in {@link Fragment#onResume}
*/
public void onResume(@Nullable Activity activity) {
public void onHostResume(@Nullable Activity activity) {
UiThreadUtil.assertOnUiThread();
mCurrentActivity = activity;
for (LifecycleEventListener listener : mLifecycleEventListeners) {
@@ -144,7 +144,7 @@ public class ReactContext extends ContextWrapper {
/**
* Should be called by the hosting Fragment in {@link Fragment#onPause}
*/
public void onPause() {
public void onHostPause() {
UiThreadUtil.assertOnUiThread();
for (LifecycleEventListener listener : mLifecycleEventListeners) {
listener.onHostPause();
@@ -154,15 +154,23 @@ public class ReactContext extends ContextWrapper {
/**
* Should be called by the hosting Fragment in {@link Fragment#onDestroy}
*/
public void onDestroy() {
public void onHostDestroy() {
UiThreadUtil.assertOnUiThread();
for (LifecycleEventListener listener : mLifecycleEventListeners) {
listener.onHostDestroy();
}
mCurrentActivity = null;
}
/**
* Destroy this instance, making it unusable.
*/
public void destroy() {
UiThreadUtil.assertOnUiThread();
if (mCatalystInstance != null) {
mCatalystInstance.destroy();
}
mCurrentActivity = null;
}
/**