Implement getReactApplicationContextIfActiveOrWarn in ReactContextBaseJavaModule to generalize checking hasActiveCatalystInstance and warning when it's dead

Summary:
In three previous diffs (D18020359 D17998627 D17969056), I implemented this logic in three different modules. There are potentially hundreds of modules where we should be implementing this check, so I'm moving the important logic into ReactContextBaseJavaModule.

Additionally, `WebSocketModule` was retaining its own copy of ReactApplicationContext instead of using the built-in `getReactApplicationContext`, so I removed that ivar from `WebSocketModule`.

Changelog:
[Internal]

Reviewed By: mdvacca

Differential Revision: D18032458

fbshipit-source-id: 9114120d3b80334df8d2e0813e36d21c667fc1bd
This commit is contained in:
Joshua Gross
2019-10-21 15:59:21 -07:00
committed by Facebook Github Bot
parent e21ed675ec
commit b12a29cfcb
3 changed files with 48 additions and 35 deletions
@@ -7,9 +7,14 @@
package com.facebook.react.bridge;
import static com.facebook.infer.annotation.ThreadConfined.ANY;
import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.ThreadConfined;
import com.facebook.react.common.build.ReactBuildConfig;
/**
* Base class for Catalyst native modules that require access to the {@link ReactContext} instance.
@@ -22,11 +27,41 @@ public abstract class ReactContextBaseJavaModule extends BaseJavaModule {
mReactApplicationContext = reactContext;
}
/** Subclasses can use this method to access catalyst context passed as a constructor */
/** Subclasses can use this method to access catalyst context passed as a constructor. */
protected final ReactApplicationContext getReactApplicationContext() {
return mReactApplicationContext;
}
/**
* Subclasses can use this method to access catalyst context passed as a constructor. Use this
* version to check that the underlying CatalystInstance is active before returning, and
* automatically have SoftExceptions or debug information logged for you. Consider using this
* whenever calling ReactApplicationContext methods that require the Catalyst instance be alive.
*
* <p>This can return null at any time, but especially during teardown methods it's
* possible/likely.
*
* <p>Threading implications have not been analyzed fully yet, so assume this method is not
* thread-safe.
*/
@ThreadConfined(ANY)
protected @Nullable final ReactApplicationContext getReactApplicationContextIfActiveOrWarn(
String tag, String reason) {
if (mReactApplicationContext.hasActiveCatalystInstance()) {
return mReactApplicationContext;
}
// We want to collect data about how often this happens, but SoftExceptions will cause a crash
// in debug mode, which isn't usually desirable.
String msg = "Catalyst Instance has already disappeared: " + reason;
if (ReactBuildConfig.DEBUG) {
FLog.w(tag, msg);
} else {
ReactSoftException.logSoftException(tag, new RuntimeException(msg));
}
return null;
}
/**
* Get the activity to which this context is currently attached, or {@code null} if not attached.
*