callstack / react-native-pager-view

React Native wrapper for the Android ViewPager and iOS UIPageViewController.
MIT License
2.72k stars 418 forks source link

[Android] Got `ANR` Error in `setPage` and `setPageWithoutAnimation` #752

Closed jinliming2 closed 1 year ago

jinliming2 commented 1 year ago

Environment

Description

I encountered an ANR error while using the library, and after some debugging, I managed to locate the source of the issue. The dispatchEvent calls in the goTo function appear to conflict with the dispatchEvent in the onPageSelected event of OnPageChangeCallback.

https://github.com/callstack/react-native-pager-view/blob/2946c1c33df6cacc8f9f77220bb879b39bb75ace/android/src/fabric/java/com/reactnativepagerview/PagerViewViewManager.kt#L167-L182

https://github.com/callstack/react-native-pager-view/blob/2946c1c33df6cacc8f9f77220bb879b39bb75ace/android/src/fabric/java/com/reactnativepagerview/PagerViewViewManager.kt#L54-L59

The ANR error occurs when calling setPage or setPageWithoutAnimation multiple times. I'm not good at Android development, but when I commented out one of the two dispatchEvent calls, the ANR error disappeared.

Reproducible Demo

import React from 'react';
import { View } from 'react-native';
import PagerView from 'react-native-pager-view';

export const App = () => {
  const ref = React.useRef<PagerView>(null);

  const [page, setPage] = React.useState(0);

  React.useEffect(() => {
    let i = 0;
    const t = setInterval(() => {
      ref.current?.setPage(i++ % 3);
    }, 1e2);
    return () => clearInterval(t);
  }, []);

  return (
    <PagerView
      ref={ref}
      onPageSelected={React.useCallback(e => setPage(e.nativeEvent.position), [])}
      style={{ flex: 1 }}
    >
      {Array.from({ length: 3 }).map((_, index) => (
        <View key={index} style={{ flex: 1, backgroundColor: ['red', 'green', 'blue'][index] }} />
      ))}
    </PagerView>
  );
};

https://github.com/callstack/react-native-pager-view/assets/10294977/af5866b6-d265-443d-80e2-4e2f23067993

SergiOnGit commented 1 year ago

Same here. ANR happens after using setPage() and then scrolling FlatList. So, ANR doesn't happen instantly after using setPage(), but after scrolling when setPage() was used.