react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

Going back in native stack cause crash on Android 7 if screen contains FlatList with refresh props (React Navigation related)

Open Zao721 opened this issue 9 months ago • 11 comments

Description

Original issue: https://github.com/react-navigation/react-navigation/issues/12510

I have such react navigation structure: Home -> Details

When Details screen contains List components (FlatList, VirtualizedList) with refresh props such as onRefresh, refreshing or refreshControl = <RefreshController...> (React Native component) going back causes app crash and it happens only on Android 7. Other Android versions work as expected.

Can be reproduced on emulators and real devices

In logcat I have two errors:

  • Exception in HostFunction: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
  • java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 1 (child count is 1)

Steps to reproduce

  1. Open example app
  2. Navigate to Details Screen
  3. Go back with ui or with hardware button

Snack or a link to a repository

https://github.com/Zao721/CrashOnGoingBackAndroid7

Screens version

^4.9.2, ^4.10.0

React Native version

78.1

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Release mode

Device

Real device

Device model

Samsung Galaxy J2 Pro (Android 7.1.1), Android Emulator 7.1.1

Acknowledgements

Yes

Zao721 avatar Mar 25 '25 17:03 Zao721

I'm also experiencing this problem

FabioRocha462 avatar Mar 26 '25 13:03 FabioRocha462

Same here with a screen containing a ScrollView

vlummien avatar Mar 26 '25 16:03 vlummien

java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 1 (child count is 1)
    at android.view.ViewGroup.getAndVerifyPreorderedIndex(ViewGroup.java:1766)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3729)
    at android.view.View.draw(View.java:18588)
    at android.view.View.updateDisplayListIfDirty(View.java:17563)
    at android.view.View.draw(View.java:18347)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3946)
    at com.facebook.react.views.view.a.drawChild(SourceFile:86)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3756)
    at com.facebook.react.views.view.a.dispatchDraw(SourceFile:18)
    at android.view.View.draw(View.java:18588)
    at com.facebook.react.views.view.a.draw(SourceFile:60)
    at android.view.View.updateDisplayListIfDirty(View.java:17563)
    at android.view.View.draw(View.java:18347)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3946)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3756)
    at android.view.View.updateDisplayListIfDirty(View.java:17558)
    at android.view.View.draw(View.java:18347)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3946)
    at androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(SourceFile:136)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3732)
    at android.view.View.updateDisplayListIfDirty(View.java:17558)
    at android.view.View.draw(View.java:18347)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3946)
    at com.swmansion.rnscreens.g.J(SourceFile:16)
    at com.swmansion.rnscreens.g.B(SourceFile:1)
    at com.swmansion.rnscreens.g$b.a(SourceFile:3)
    at com.swmansion.rnscreens.g.F(SourceFile:26)
    at com.swmansion.rnscreens.g.dispatchDraw(SourceFile:61)
    at android.view.View.updateDisplayListIfDirty(View.java:17558)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3930)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3910)
    at android.view.View.updateDisplayListIfDirty(View.java:17526)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:711)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:717)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:825)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:3209)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2996)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2584)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1569)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7301)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:930)
    at android.view.Choreographer.doCallbacks(Choreographer.java:705)
    at android.view.Choreographer.doFrame(Choreographer.java:640)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:916)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6816)
    at java.lang.reflect.Method.invoke(Method.java)

astrahov avatar Mar 28 '25 07:03 astrahov

Error: Exception in HostFunction: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
	at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7988)
	at android.view.ViewRo...
  at android.view.ViewRootImpl.checkThread(app:///ViewRootImpl.java:7988)
  at android.view.ViewRootImpl.invalidateChildInParent(app:///ViewRootImpl.java:1392)
  at android.view.ViewGroup.invalidateChild(app:///ViewGroup.java:5426)
  at android.view.View.invalidateInternal(app:///View.java:14985)
  at android.view.View.invalidate(app:///View.java:14949)
  at android.view.ViewGroup.addView(app:///ViewGroup.java:4476)
  at android.view.ViewGroup.addView(app:///ViewGroup.java:4417)
  at com.swmansion.rnscreens.b.u(app:///SourceFile:31)
  at com.swmansion.rnscreens.b.u(app:///SourceFile:60)
  at com.swmansion.rnscreens.b.u(app:///SourceFile:60)
  at com.swmansion.rnscreens.b.t(app:///SourceFile:8)
  at com.swmansion.rnscreens.NativeProxy.notifyScreenRemoved(app:///SourceFile:24)
  at com.facebook.jni.NativeRunnable.run(app:///Native Method)
  at android.os.Handler.handleCallback(app:///Handler.java:751)
  at android.os.Handler.dispatchMessage(app:///Handler.java:95)
  at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(app:///SourceFile:1)
  at android.os.Looper.loop(app:///Looper.java:154)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl.lambda$startNewBackgroundThread$2(app:///SourceFile:36)
  at com.facebook.react.bridge.queue.MessageQueueThreadImpl.b(app:///SourceFile:1)
  at aD.run(app:///SourceFile:1)
  at java.lang.Thread.run(app:///Thread.java:762)
  at completeRoot(native)
  at updateHostContainer(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:6090:17)
  at completeWork(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:6180:28)
  at completeUnitOfWork(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8298:28)
  at performUnitOfWork(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8189:37)
  at workLoopSync(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8080:54)
  at renderRootSync(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8060:19)
  at flushSyncWorkAcrossRoots_impl(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:1924:48)
  at processRootScheduleInMicrotask(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:2015:32)
  at scheduleMicrotask$argument_0(node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:2093:15)

astrahov avatar Mar 28 '25 09:03 astrahov

Error Exception in HostFunction: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. (native) completeRoot node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:6090:16 updateHostContainer node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:6180:27 completeWork node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8298:27 completeUnitOfWork node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8189:36 performUnitOfWork node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8080:53 workLoopSync node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:8060:18 renderRootSync node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:1924:47 flushSyncWorkAcrossRoots_impl node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:2015:31 processRootScheduleInMicrotask node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-prod.js:2093:14 anonymous

RodrigoAngeloValentini avatar Apr 16 '25 13:04 RodrigoAngeloValentini

+1

harpreetsingh1627484 avatar Apr 18 '25 16:04 harpreetsingh1627484

+1

c-info avatar May 27 '25 07:05 c-info

we're facing the same issue as well. it happens occasionally. this happens on ^4.11.0-beta.2


java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 2 (child count is 2)
  android.view.ViewGroup.getAndVerifyPreorderedIndex(ViewGroup.java:2122)
  android.view.ViewGroup.dispatchDraw(ViewGroup.java:4416)
  android.view.View.draw(View.java:26165)
  android.view.View.updateDisplayListIfDirty(View.java:24922)
  android.view.View.draw(View.java:25851)
  android.view.ViewGroup.drawChild(ViewGroup.java:4670)
  com.facebook.react.views.view.ReactViewGroup.drawChild(ReactViewGroup.java:975)
  android.view.ViewGroup.dispatchDraw(ViewGroup.java:4443)
  com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:946)
  android.view.View.draw(View.java:26165)
  com.facebook.react.views.view.ReactViewGroup.draw(ReactViewGroup.java:937)
  android.view.View.updateDisplayListIfDirty(View.java:24922)
  android.view.View.draw(View.java:25851)
  android.view.ViewGroup.drawChild(ViewGroup.java:4670)
  android.view.ViewGroup.dispatchDraw(ViewGroup.java:4443)
  android.view.View.updateDisplayListIfDirty(View.java:24909)
  android.view.View.draw(View.java:25851)
  android.view.ViewGroup.drawChild(ViewGroup.java:4670)
  androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1312)
  android.view.ViewGroup.dispatchDraw(ViewGroup.java:4419)
  android.view.View.updateDisplayListIfDirty(View.java:24909)
  android.view.View.draw(View.java:25851)
  android.view.ViewGroup.drawChild(ViewGroup.java:4670)
  com.swmansion.rnscreens.ScreenStack.performDraw(ScreenStack.kt:334)
  com.swmansion.rnscreens.ScreenStack.access$performDraw(ScreenStack.kt:20)
  com.swmansion.rnscreens.ScreenStack$DrawingOp.draw(ScreenStack.kt:347)
  com.swmansion.rnscreens.ScreenStack.drawAndRelease(ScreenStack.kt:303)
  com.swmansion.rnscreens.ScreenStack.dispatchDraw(ScreenStack.kt:313)
  android.view.View.updateDisplayListIfDirty(View.java:24909)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4654)
  android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4627)
  android.view.View.updateDisplayListIfDirty(View.java:24844)
  android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:744)
  android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:753)
  android.view.ThreadedRenderer.draw(ThreadedRenderer.java:859)
  android.view.ViewRootImpl.draw(ViewRootImpl.java:6540)
  android.view.ViewRootImpl.performDraw(ViewRootImpl.java:6146)
  android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:5028)
  android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3545)
  android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:11739)
  android.view.Choreographer$CallbackRecord.run(Choreographer.java:1794)
  android.view.Choreographer$CallbackRecord.run(Choreographer.java:1803)
  android.view.Choreographer.doCallbacks(Choreographer.java:1295)
  android.view.Choreographer.doFrame(Choreographer.java:1171)
  android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1762)
  android.os.Handler.handleCallback(Handler.java:959)
  android.os.Handler.dispatchMessage(Handler.java:100)
  android.os.Looper.loopOnce(Looper.java:249)
  android.os.Looper.loop(Looper.java:337)
  android.app.ActivityThread.main(ActivityThread.java:9486)
  java.lang.reflect.Method.invoke(Native Method)
  com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:636)
  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1004)

a-eid avatar May 27 '25 11:05 a-eid

I also encountered the same problem:

"react-native-screens": "4.11.0",
"react-native": "0.78.2",

astrahov avatar May 27 '25 15:05 astrahov

Hi, I'm attaching patch that should help with this issue. I created also a PR with those changes, but we're not sure if it will land in release as it may cause other problems.

react-native-screens+4.11.1.patch

maciekstosio avatar Jun 10 '25 14:06 maciekstosio

Hey, thanks for the patch. Ran into this recently and that fixed it. About the other problems, I read the PR and it seems to be a concurrency issue? Do you know what side effects this could have? I haven't been able to cause anything.

goege64 avatar Jun 30 '25 20:06 goege64

@maciekstosio @kkafar is there any delay to getting this patch into a library version?

heathercodes avatar Jul 24 '25 12:07 heathercodes

Hey, thanks for the patch. Ran into this recently and that fixed it. About the other problems, I read the PR and it seems to be a concurrency issue? Do you know what side effects this could have? I haven't been able to cause anything.

since we have no visibility on when a new release will come, did you face any side effect with this patch one month later? :)

pierroo avatar Jul 28 '25 18:07 pierroo

Hey, thanks for the patch. Ran into this recently and that fixed it. About the other problems, I read the PR and it seems to be a concurrency issue? Do you know what side effects this could have? I haven't been able to cause anything.

since we have no visibility on when a new release will come, did you face any side effect with this patch one month later? :)

nothing yet, though im not sure its been enough to conclude much (not many people still use android 7). just to note, i changed the patch to only do the scheduling on android 7, so i wouldnt know about other versions

goege64 avatar Jul 29 '25 12:07 goege64

Hi, I'm attaching patch that should help with this issue. I created also a PR with those changes, but we're not sure if it will land in release as it may cause other problems.

react-native-screens+4.11.1.patch

I have the same problem (Android 7.1, react-native-screens 4.15.2, react-native 0.80.1) The patch helped - the problem disappeared

drlivsi avatar Aug 24 '25 08:08 drlivsi

By any chance, was this issue resolved in recent 4.15.x versions? or is the patch for 4.11.1 the only way?

pierroo avatar Aug 27 '25 07:08 pierroo