Skip to content

Commit 198f5ca

Browse files
committed
Re-arm the timers frame callback on the UI thread
createTimer can run on the native module thread; ReactChoreographer must be driven from the UI looper (its null-choreographer fallback hop does not cover the initialized case). Route the lazy re-arm through setChoreographerCallback on the UI queue, which is idempotent and already used by onHostResume.
1 parent ec37b64 commit 198f5ca

1 file changed

Lines changed: 10 additions & 12 deletions

File tree

  • packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,18 +186,16 @@ public open class JavaTimerManager(
186186
synchronized(timerGuard) {
187187
timers.add(timer)
188188
timerIdsToTimers.put(timerId, timer)
189-
if (ReactNativeFeatureFlags.disableIdleTimersFrameCallbackRearmAndroid() &&
190-
!frameCallbackPosted &&
191-
(!isPaused.get() || isRunningTasks.get())) {
192-
// The timers frame callback disarms itself once the queue drains (see TimerFrameCallback);
193-
// re-arm it lazily when a new timer arrives. While the host is paused, only headless JS
194-
// task execution may run timers — mirroring the guard in clearFrameCallback.
195-
reactChoreographer.postFrameCallback(
196-
ReactChoreographer.CallbackType.TIMERS_EVENTS,
197-
timerFrameCallback,
198-
)
199-
frameCallbackPosted = true
200-
}
189+
}
190+
if (ReactNativeFeatureFlags.disableIdleTimersFrameCallbackRearmAndroid() &&
191+
!frameCallbackPosted &&
192+
(!isPaused.get() || isRunningTasks.get())) {
193+
// The timers frame callback disarms itself once the queue drains (see TimerFrameCallback);
194+
// re-arm it lazily when a new timer arrives. setChoreographerCallback is UI-confined
195+
// (ReactChoreographer must be driven from the UI looper) and idempotent, so hop to the UI
196+
// thread. While the host is paused, only headless JS task execution may run timers —
197+
// mirroring the guard in clearFrameCallback.
198+
UiThreadUtil.runOnUiThread { setChoreographerCallback() }
201199
}
202200
}
203201

0 commit comments

Comments
 (0)