diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/internal/interop/InteropUiBlockListener.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/internal/interop/InteropUiBlockListener.kt index 5435a35dbe1346..c9b7b1540b8e26 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/internal/interop/InteropUiBlockListener.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/internal/interop/InteropUiBlockListener.kt @@ -39,27 +39,35 @@ internal class InteropUIBlockListener : UIManagerListener { } override fun willMountItems(uiManager: UIManager) { - if (beforeUIBlocks.isEmpty()) { - return + val blocksToExecute: List = synchronized(this) { + if (beforeUIBlocks.isEmpty()) { + return + } + beforeUIBlocks.toList().also { beforeUIBlocks.clear() } } - beforeUIBlocks.forEach { - if (uiManager is UIBlockViewResolver) { - it.execute(uiManager) + + if (uiManager is UIBlockViewResolver) { + // avoid ConcurrentModificationException by iterating over a copy + blocksToExecute.forEach { block -> + block.execute(uiManager) } } - beforeUIBlocks.clear() } override fun didMountItems(uiManager: UIManager) { - if (afterUIBlocks.isEmpty()) { - return + val blocksToExecute: List = synchronized(this) { + if (afterUIBlocks.isEmpty()) { + return + } + afterUIBlocks.toList().also { afterUIBlocks.clear() } } - afterUIBlocks.forEach { - if (uiManager is UIBlockViewResolver) { - it.execute(uiManager) + + if (uiManager is UIBlockViewResolver) { + // avoid ConcurrentModificationException by iterating over a copy + blocksToExecute.forEach { block -> + block.execute(uiManager) } } - afterUIBlocks.clear() } override fun didDispatchMountItems(uiManager: UIManager) = didMountItems(uiManager)