diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 4b0a84f5a..020ac08b6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -933,12 +933,14 @@ public class ReactInstanceManager { ? mNativeModuleCallExceptionHandler : mDevSupportManager; CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder() - .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault()) - .setJSExecutor(jsExecutor) - .setRegistry(nativeModuleRegistry) - .setJSModuleRegistry(jsModulesBuilder.build()) - .setJSBundleLoader(jsBundleLoader) - .setNativeModuleCallExceptionHandler(exceptionHandler); + .setReactQueueConfigurationSpec(mUseSeparateUIBackgroundThread ? + ReactQueueConfigurationSpec.createWithSeparateUIBackgroundThread() : + ReactQueueConfigurationSpec.createDefault()) + .setJSExecutor(jsExecutor) + .setRegistry(nativeModuleRegistry) + .setJSModuleRegistry(jsModulesBuilder.build()) + .setJSBundleLoader(jsBundleLoader) + .setNativeModuleCallExceptionHandler(exceptionHandler); ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START); // CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 28bd58cb9..9d8116d2d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -308,6 +308,10 @@ public class ReactContext extends ContextWrapper { Assertions.assertNotNull(mJSMessageQueueThread).runOnQueue(runnable); } + public boolean hasUIBackgroundRunnableThread() { + return mUiBackgroundMessageQueueThread != null; + } + public void runUIBackgroundRunnable(Runnable runnable) { if (mUiBackgroundMessageQueueThread == null) { runOnNativeModulesQueueThread(runnable); diff --git a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java index 23fcced80..04b5f5973 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/cxxbridge/CatalystInstanceImpl.java @@ -89,6 +89,7 @@ public class CatalystInstanceImpl implements CatalystInstance { private final NativeModuleRegistry mJavaRegistry; private final NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final MessageQueueThread mNativeModulesQueueThread; + private final @Nullable MessageQueueThread mUIBackgroundQueueThread; private boolean mInitialized = false; private volatile boolean mAcceptCalls = false; @@ -118,6 +119,7 @@ public class CatalystInstanceImpl implements CatalystInstance { mJSBundleLoader = jsBundleLoader; mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; mNativeModulesQueueThread = mReactQueueConfiguration.getNativeModulesQueueThread(); + mUIBackgroundQueueThread = mReactQueueConfiguration.getUIBackgroundQueueThread(); mTraceListener = new JSProfilerTraceListener(this); FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge"); @@ -126,6 +128,7 @@ public class CatalystInstanceImpl implements CatalystInstance { jsExecutor, mReactQueueConfiguration.getJSQueueThread(), mNativeModulesQueueThread, + mUIBackgroundQueueThread, mJavaRegistry.getJavaModules(this), mJavaRegistry.getCxxModules()); FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge"); @@ -171,6 +174,7 @@ public class CatalystInstanceImpl implements CatalystInstance { JavaScriptExecutor jsExecutor, MessageQueueThread jsQueue, MessageQueueThread moduleQueue, + MessageQueueThread uiBackgroundQueue, Collection javaModules, Collection cxxModules); diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp index 75212aa7d..2b7dfd35c 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.cpp @@ -86,8 +86,10 @@ CatalystInstanceImpl::CatalystInstanceImpl() : instance_(folly::make_unique()) {} CatalystInstanceImpl::~CatalystInstanceImpl() { - // TODO: 16669252: this prevents onCatalystInstanceDestroy from being called moduleMessageQueue_->quitSynchronous(); + if (uiBackgroundMessageQueue_ != NULL) { + uiBackgroundMessageQueue_->quitSynchronous(); + } } void CatalystInstanceImpl::registerNatives() { @@ -118,11 +120,15 @@ void CatalystInstanceImpl::initializeBridge( JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref nativeModulesQueue, + jni::alias_ref uiBackgroundQueue, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules) { // TODO mhorowitz: how to assert here? // Assertions.assertCondition(mBridge == null, "initializeBridge should be called once"); moduleMessageQueue_ = std::make_shared(nativeModulesQueue); + if (uiBackgroundQueue.get() != nullptr) { + uiBackgroundMessageQueue_ = std::make_shared(uiBackgroundQueue); + } // This used to be: // @@ -141,11 +147,17 @@ void CatalystInstanceImpl::initializeBridge( // stack. instance_->initializeBridge( - folly::make_unique(callback, moduleMessageQueue_), + folly::make_unique( + callback, + uiBackgroundMessageQueue_ != NULL ? uiBackgroundMessageQueue_ : moduleMessageQueue_), jseh->getExecutorFactory(), folly::make_unique(jsQueue), buildModuleRegistry( - std::weak_ptr(instance_), javaModules, cxxModules, moduleMessageQueue_)); + std::weak_ptr(instance_), + javaModules, + cxxModules, + moduleMessageQueue_, + uiBackgroundMessageQueue_)); } void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { diff --git a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h index 23edbb9c2..391d195b1 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/xreact/jni/CatalystInstanceImpl.h @@ -48,6 +48,7 @@ class CatalystInstanceImpl : public jni::HybridClass { JavaScriptExecutorHolder* jseh, jni::alias_ref jsQueue, jni::alias_ref moduleQueue, + jni::alias_ref uiBackgroundQueue, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules); @@ -74,6 +75,7 @@ class CatalystInstanceImpl : public jni::HybridClass { // will have a weak reference. std::shared_ptr instance_; std::shared_ptr moduleMessageQueue_; + std::shared_ptr uiBackgroundMessageQueue_; }; }} diff --git a/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h index 67ff2efad..6ab0d6406 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h +++ b/ReactAndroid/src/main/jni/xreact/jni/JavaModuleWrapper.h @@ -34,6 +34,11 @@ struct JavaModuleWrapper : jni::JavaClass { return getModule(self()); } + std::string getName() const { + static auto getName = javaClassStatic()->getMethod("getName"); + return getName(self())->toStdString(); + } + jni::local_ref::javaobject> getMethodDescriptors() { static auto getMethods = getClass() ->getMethod::javaobject()>("getMethodDescriptors"); diff --git a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.cpp b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.cpp index 8633f7833..73ad22a13 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.cpp +++ b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.cpp @@ -33,12 +33,25 @@ std::unique_ptr buildModuleRegistry( std::weak_ptr winstance, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules, - std::shared_ptr moduleMessageQueue) { + std::shared_ptr moduleMessageQueue, + std::shared_ptr uiBackgroundMessageQueue) { std::vector> modules; if (javaModules) { for (const auto& jm : *javaModules) { - modules.emplace_back(folly::make_unique( + std::string name = jm->getName(); + if (uiBackgroundMessageQueue != NULL && + // This is techinically a hack. Perhaps we should bind the specific queue to the module + // in the module holder or wrapper. + // TODO expose as module configuration option + (name == "UIManager" || + name == "NativeAnimatedModule" || + name == "FBFacebookReactNavigator")) { + modules.emplace_back(folly::make_unique( + winstance, jm, uiBackgroundMessageQueue)); + } else { + modules.emplace_back(folly::make_unique( winstance, jm, moduleMessageQueue)); + } } } if (cxxModules) { diff --git a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.h b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.h index 0aeb7d539..b17664cd9 100644 --- a/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.h +++ b/ReactAndroid/src/main/jni/xreact/jni/ModuleRegistryBuilder.h @@ -27,7 +27,7 @@ std::unique_ptr buildModuleRegistry( std::weak_ptr winstance, jni::alias_ref::javaobject> javaModules, jni::alias_ref::javaobject> cxxModules, - std::shared_ptr moduleMessageQueue); - + std::shared_ptr moduleMessageQueue, + std::shared_ptr uiBackgroundMessageQueue); } }