Allow reactinstancemanager to set an initialization function
Reviewed By: javache Differential Revision: D5227811 fbshipit-source-id: e7868481de2a8799af5d6a6bcad26369d054b35e
This commit is contained in:
parent
6783694158
commit
84e80eb781
|
@ -55,6 +55,7 @@ import com.facebook.react.bridge.ReactContext;
|
|||
import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.ReactMarkerConstants;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.NativeArray;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
|
@ -105,6 +106,8 @@ import javax.annotation.Nullable;
|
|||
@ThreadSafe
|
||||
public class ReactInstanceManager {
|
||||
|
||||
private static final String TAG = ReactInstanceManager.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Listener interface for react instance events.
|
||||
*/
|
||||
|
@ -127,6 +130,7 @@ public class ReactInstanceManager {
|
|||
private final @Nullable JSBundleLoader mBundleLoader; /* path to JS bundle on file system */
|
||||
private final @Nullable String mJSMainModulePath; /* path to JS bundle root on packager server */
|
||||
private final List<ReactPackage> mPackages;
|
||||
private final List<CatalystInstanceImpl.PendingJSCall> mInitFunctions;
|
||||
private final DevSupportManager mDevSupportManager;
|
||||
private final boolean mUseDeveloperSupport;
|
||||
private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
|
||||
|
@ -232,6 +236,7 @@ public class ReactInstanceManager {
|
|||
mBundleLoader = bundleLoader;
|
||||
mJSMainModulePath = jsMainModulePath;
|
||||
mPackages = new ArrayList<>();
|
||||
mInitFunctions = new ArrayList<>();
|
||||
mUseDeveloperSupport = useDeveloperSupport;
|
||||
mDevSupportManager = DevSupportManagerFactory.create(
|
||||
applicationContext,
|
||||
|
@ -351,11 +356,33 @@ public class ReactInstanceManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Recreate the react application and context. This should be called if configuration has
|
||||
* changed or the developer has requested the app to be reloaded. It should only be called after
|
||||
* an initial call to createReactContextInBackground.
|
||||
* If the JavaScript bundle for this app requires initialization as part of bridge start up,
|
||||
* register a function using its @param module and @param method and optional arguments.
|
||||
*/
|
||||
public void registerInitFunction(String module, String method, @Nullable NativeArray arguments) {
|
||||
CatalystInstanceImpl.PendingJSCall init =
|
||||
new CatalystInstanceImpl.PendingJSCall(module, method, arguments);
|
||||
synchronized (this) {
|
||||
mInitFunctions.add(init);
|
||||
}
|
||||
ReactContext context = getCurrentReactContext();
|
||||
CatalystInstance catalystInstance = context == null ? null : context.getCatalystInstance();
|
||||
if (catalystInstance == null) {
|
||||
return;
|
||||
} else {
|
||||
// CatalystInstance is only visible after running jsBundle, so these will be put on the native
|
||||
// JS queue
|
||||
// TODO T20546472 remove cast when catalystInstance and InstanceImpl are renamed/merged
|
||||
((CatalystInstanceImpl) catalystInstance).callFunction(init);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreate the react application and context. This should be called if configuration has changed
|
||||
* or the developer has requested the app to be reloaded. It should only be called after an
|
||||
* initial call to createReactContextInBackground.
|
||||
*
|
||||
* Called from UI thread.
|
||||
* <p>Called from UI thread.
|
||||
*/
|
||||
@ThreadConfined(UI)
|
||||
public void recreateReactContextInBackground() {
|
||||
|
@ -995,10 +1022,19 @@ public class ReactInstanceManager {
|
|||
if (Systrace.isTracing(TRACE_TAG_REACT_APPS | TRACE_TAG_REACT_JSC_CALLS)) {
|
||||
catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
|
||||
}
|
||||
catalystInstance.runJSBundle();
|
||||
|
||||
// Transitions functions in the minitFunctions list to catalystInstance, to run after the bundle
|
||||
// TODO T20546472
|
||||
if (!mInitFunctions.isEmpty()) {
|
||||
for (CatalystInstanceImpl.PendingJSCall function : mInitFunctions) {
|
||||
((CatalystInstanceImpl) catalystInstance).callFunction(function);
|
||||
}
|
||||
}
|
||||
ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
|
||||
|
||||
reactContext.initializeWithInstance(catalystInstance);
|
||||
ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
|
||||
catalystInstance.runJSBundle();
|
||||
|
||||
|
||||
return reactContext;
|
||||
}
|
||||
|
|
|
@ -43,20 +43,27 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
|
||||
private static final AtomicInteger sNextInstanceIdForTrace = new AtomicInteger(1);
|
||||
|
||||
private static class PendingJSCall {
|
||||
public static class PendingJSCall {
|
||||
|
||||
public String mModule;
|
||||
public String mMethod;
|
||||
public NativeArray mArguments;
|
||||
public @Nullable NativeArray mArguments;
|
||||
|
||||
public PendingJSCall(
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments) {
|
||||
public PendingJSCall(String module, String method, @Nullable NativeArray arguments) {
|
||||
mModule = module;
|
||||
mMethod = method;
|
||||
mArguments = arguments;
|
||||
}
|
||||
|
||||
void call(CatalystInstanceImpl catalystInstance) {
|
||||
NativeArray arguments = mArguments != null ? mArguments : new WritableNativeArray();
|
||||
catalystInstance.jniCallJSFunction(mModule, mMethod, arguments);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return mModule + "." + mMethod + "("
|
||||
+ (mArguments == null ? "" : mArguments.toString()) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
// Access from any thread
|
||||
|
@ -216,7 +223,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
public void runJSBundle() {
|
||||
Log.d(ReactConstants.TAG, "CatalystInstanceImpl.runJSBundle()");
|
||||
Assertions.assertCondition(!mJSBundleHasLoaded, "JS bundle was already loaded!");
|
||||
|
||||
// incrementPendingJSCalls();
|
||||
mJSBundleLoader.loadScript(CatalystInstanceImpl.this);
|
||||
|
||||
|
@ -227,8 +233,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
// gates will be queued on the JS thread behind the load.
|
||||
mAcceptCalls = true;
|
||||
|
||||
for (PendingJSCall call : mJSCallsPendingInit) {
|
||||
jniCallJSFunction(call.mModule, call.mMethod, call.mArguments);
|
||||
for (PendingJSCall function : mJSCallsPendingInit) {
|
||||
function.call(this);
|
||||
}
|
||||
mJSCallsPendingInit.clear();
|
||||
mJSBundleHasLoaded = true;
|
||||
|
@ -260,8 +266,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
final String module,
|
||||
final String method,
|
||||
final NativeArray arguments) {
|
||||
callFunction(new PendingJSCall(module, method, arguments));
|
||||
}
|
||||
|
||||
public void callFunction(PendingJSCall function) {
|
||||
if (mDestroyed) {
|
||||
final String call = module + "." + method + "(" + arguments.toString() + ")";
|
||||
final String call = function.toString();
|
||||
FLog.w(ReactConstants.TAG, "Calling JS function after bridge has been destroyed: " + call);
|
||||
return;
|
||||
}
|
||||
|
@ -269,13 +279,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
|||
// Most of the time the instance is initialized and we don't need to acquire the lock
|
||||
synchronized (mJSCallsPendingInitLock) {
|
||||
if (!mAcceptCalls) {
|
||||
mJSCallsPendingInit.add(new PendingJSCall(module, method, arguments));
|
||||
mJSCallsPendingInit.add(function);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jniCallJSFunction(module, method, arguments);
|
||||
function.call(this);
|
||||
}
|
||||
|
||||
private native void jniCallJSCallback(int callbackID, NativeArray arguments);
|
||||
|
|
|
@ -186,14 +186,13 @@ public class StackTraceHelper {
|
|||
Matcher matcher = STACK_FRAME_PATTERN.matcher(stackTrace[i]);
|
||||
if (!matcher.find()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected stack frame format: " + stackTrace[i]);
|
||||
"Unexpected stack frame format: " + stackTrace[i]);
|
||||
}
|
||||
|
||||
result[i] = new StackFrameImpl(
|
||||
matcher.group(2),
|
||||
matcher.group(1) == null ? "(unknown)" : matcher.group(1),
|
||||
Integer.parseInt(matcher.group(3)),
|
||||
Integer.parseInt(matcher.group(4)));
|
||||
matcher.group(2),
|
||||
matcher.group(1) == null ? "(unknown)" : matcher.group(1),
|
||||
Integer.parseInt(matcher.group(3)),
|
||||
Integer.parseInt(matcher.group(4)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -88,6 +88,7 @@ public class ReactModuleSpecProcessor extends AbstractProcessor {
|
|||
|
||||
TypeElement typeElement = (TypeElement) reactModuleListElement;
|
||||
ReactModuleList reactModuleList = typeElement.getAnnotation(ReactModuleList.class);
|
||||
|
||||
if (reactModuleList == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue