From 49129588123fe05c828fae036b9521f4ba6fe84c Mon Sep 17 00:00:00 2001 From: Zeya Peng Date: Mon, 31 Mar 2025 13:17:56 -0700 Subject: [PATCH] `synchronouslyUpdateViewOnUIThread` on UIManager (#50379) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50379 ## Changelog: [Android] [Added] - Allow invoking `synchronouslyUpdateViewOnUIThread` from c++ via `UIManager` implementation is provided by SchedulerDelegate on the platform Reviewed By: javache Differential Revision: D71648772 fbshipit-source-id: bba0f7e9e2deafd074d28ff5cece6b7738c4d123 --- packages/react-native/React/Fabric/RCTScheduler.mm | 6 ++++++ .../src/main/jni/react/fabric/FabricUIManagerBinding.cpp | 4 ++++ .../src/main/jni/react/fabric/FabricUIManagerBinding.h | 4 ++++ .../ReactCommon/react/renderer/scheduler/Scheduler.cpp | 8 ++++++++ .../ReactCommon/react/renderer/scheduler/Scheduler.h | 3 +++ .../react/renderer/scheduler/SchedulerDelegate.h | 4 ++++ .../ReactCommon/react/renderer/uimanager/UIManager.cpp | 8 ++++++++ .../ReactCommon/react/renderer/uimanager/UIManager.h | 2 ++ .../react/renderer/uimanager/UIManagerDelegate.h | 7 +++++++ 9 files changed, 46 insertions(+) diff --git a/packages/react-native/React/Fabric/RCTScheduler.mm b/packages/react-native/React/Fabric/RCTScheduler.mm index 9bfb79f84d4..5e830fe9610 100644 --- a/packages/react-native/React/Fabric/RCTScheduler.mm +++ b/packages/react-native/React/Fabric/RCTScheduler.mm @@ -68,6 +68,12 @@ class SchedulerDelegateProxy : public SchedulerDelegate { [scheduler.delegate schedulerDidSendAccessibilityEvent:shadowView eventType:eventType]; } + void schedulerShouldSynchronouslyUpdateViewOnUIThread(facebook::react::Tag tag, const folly::dynamic &props) override + { + // Does nothing. + // This delegate method is not currently used on iOS. + } + private: void *scheduler_; }; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp index 58de57781b4..7fcbb024f3c 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp @@ -620,6 +620,10 @@ void FabricUIManagerBinding::schedulerDidSetIsJSResponder( shadowView, isJSResponder, blockNativeResponder); } +void FabricUIManagerBinding::schedulerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) {} + void FabricUIManagerBinding::onAnimationStarted() { auto mountingManager = getMountingManager("onAnimationStarted"); if (!mountingManager) { diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h index 50c234eca5f..c3c404c9990 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h @@ -120,6 +120,10 @@ class FabricUIManagerBinding : public jni::HybridClass, bool isJSResponder, bool blockNativeResponder) override; + void schedulerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) override; + void setPixelDensity(float pointScaleFactor); void driveCxxAnimations(); diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 20a96109746..05f7b0e9d12 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -320,6 +320,14 @@ void Scheduler::uiManagerDidSetIsJSResponder( } } +void Scheduler::uiManagerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) { + if (delegate_ != nullptr) { + delegate_->schedulerShouldSynchronouslyUpdateViewOnUIThread(tag, props); + } +} + void Scheduler::reportMount(SurfaceId surfaceId) const { uiManager_->reportMount(surfaceId); } diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h index 4e364dbe6fc..6972502b4f5 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h @@ -95,6 +95,9 @@ class Scheduler final : public UIManagerDelegate { const ShadowNode::Shared& shadowNode, bool isJSResponder, bool blockNativeResponder) override; + void uiManagerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) override; #pragma mark - ContextContainer ContextContainer::Shared getContextContainer() const; diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h b/packages/react-native/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h index 1f84bd582c2..4457ce76a76 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h @@ -64,6 +64,10 @@ class SchedulerDelegate { bool isJSResponder, bool blockNativeResponder) = 0; + virtual void schedulerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) = 0; + virtual ~SchedulerDelegate() noexcept = default; }; diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index bf5323bd211..36a9ca86be0 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -690,4 +690,12 @@ void UIManager::animationTick() const { } } +void UIManager::synchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) { + if (delegate_ != nullptr) { + delegate_->uiManagerShouldSynchronouslyUpdateViewOnUIThread(tag, props); + } +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h index 674b812510c..f57eee932eb 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h @@ -70,6 +70,8 @@ class UIManager final : public ShadowTreeDelegate { void animationTick() const; + void synchronouslyUpdateViewOnUIThread(Tag tag, const folly::dynamic& props); + /* * Provides access to a UIManagerBindging. * The `callback` methods will not be called if the internal pointer to diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h index 46b78957705..581a1096ba7 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h @@ -58,6 +58,13 @@ class UIManagerDelegate { bool isJSResponder, bool blockNativeResponder) = 0; + /* + * Synchronous view update. + */ + virtual void uiManagerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) = 0; + virtual ~UIManagerDelegate() noexcept = default; };