meliorence / react-native-snap-carousel

Swiper/carousel component for React Native featuring previews, multiple layouts, parallax images, performant handling of huge numbers of items, and more. Compatible with Android & iOS.
BSD 3-Clause "New" or "Revised" License
10.36k stars 2.29k forks source link

"Failed to dispatch window animation state change" crash occasionally on Android LayoutAnimation #375

Closed narobertson42 closed 2 months ago

narobertson42 commented 6 years ago

I posted this in react-native issues but feel it might be more appropriate to post it here as appears to be associated with the Carousel component in particular.

React-Native Issue

Environment

Environment: OS: macOS High Sierra 10.13.6 Node: 10.4.1 Yarn: 1.7.0 npm: 6.2.0 Watchman: Not Found Xcode: Xcode 9.4.1 Build version 9F2000 Android Studio: 3.1 AI-173.4720617

Packages: (wanted => installed) react: 16.4.1 => 16.4.1 react-native: ~0.56.0 => 0.56.0

Description

This is tough to reproduce, I haven't been able to recreate this issue in a nice sandbox environment, however I have shared the general structure of the code along with the error log in the hope that somebody else might be able to see how to recreate it.

Appears to be similar to issue #7165

Devices affected by the crash: Moto G3 (Android 6.0.1) and Huawei P9 (Android 7)

Devices not affected by the crash: Pixel 2 (Android 9)

The issue stops when you remove all LayoutAnimations from the code

Crashlog

08-16 11:35:37.495   284   284 F DEBUG   : Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI CallObjectMethod called with pending exception java.lang.IllegalStateException: Unable to create layer for ReactHorizontalScrollContainerView'
08-16 11:35:37.495   284   284 F DEBUG   :     r0 00000000  r1 00003240  r2 00000006  r3 b6ff7b7c
08-16 11:35:37.495   284   284 F DEBUG   :     r4 b6ff7b84  r5 b6ff7b34  r6 0000000b  r7 0000010c
08-16 11:35:37.495   284   284 F DEBUG   :     r8 b761aff8  r9 b4dfc378  sl 00000000  fp 00000000
08-16 11:35:37.495   284   284 F DEBUG   :     ip 00000006  sp bef68b20  lr b6d7d1dd  pc b6d7f5d8  cpsr 40070010
08-16 11:35:37.508   284   284 F DEBUG   :
08-16 11:35:37.508   284   284 F DEBUG   : backtrace:
08-16 11:35:37.508   284   284 F DEBUG   :     #00 pc 000445d8  /system/lib/libc.so (tgkill+12)
08-16 11:35:37.508   284   284 F DEBUG   :     #01 pc 000421d9  /system/lib/libc.so (pthread_kill+32)
08-16 11:35:37.508   284   284 F DEBUG   :     #02 pc 0001bb1f  /system/lib/libc.so (raise+10)
08-16 11:35:37.508   284   284 F DEBUG   :     #03 pc 00018cc1  /system/lib/libc.so (__libc_android_abort+34)
08-16 11:35:37.509   284   284 F DEBUG   :     #04 pc 00016880  /system/lib/libc.so (abort+4)
08-16 11:35:37.509   284   284 F DEBUG   :     #05 pc 00321ac9  /system/lib/libart.so (_ZN3art7Runtime5AbortEv+212)
08-16 11:35:37.509   284   284 F DEBUG   :     #06 pc 000f3d4d  /system/lib/libart.so (_ZN3art10LogMessageD2Ev+2212)
08-16 11:35:37.509   284   284 F DEBUG   :     #07 pc 0024fa55  /system/lib/libart.so (_ZN3art9JavaVMExt8JniAbortEPKcS2_+1524)
08-16 11:35:37.509   284   284 F DEBUG   :     #08 pc 0024fdf7  /system/lib/libart.so (_ZN3art9JavaVMExt9JniAbortVEPKcS2_St9__va_list+54)
08-16 11:35:37.509   284   284 F DEBUG   :     #09 pc 000fc0f3  /system/lib/libart.so (_ZN3art11ScopedCheck6AbortFEPKcz+30)
08-16 11:35:37.509   284   284 F DEBUG   :     #10 pc 00100fcf  /system/lib/libart.so (_ZN3art11ScopedCheck5CheckERNS_18ScopedObjectAccessEbPKcPNS_12JniValueTypeE.constprop.95+5054)
08-16 11:35:37.509   284   284 F DEBUG   :     #11 pc 0010f083  /system/lib/libart.so (_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_9Primitive4TypeENS_10InvokeTypeE+498)
08-16 11:35:37.509   284   284 F DEBUG   :     #12 pc 0011065f  /system/lib/libart.so (_ZN3art8CheckJNI16CallObjectMethodEP7_JNIEnvP8_jobjectP10_jmethodIDz+38)
08-16 11:35:37.509   284   284 F DEBUG   :     #13 pc 00002bc3  /system/lib/libnativehelper.so (jniGetReferent+94)
08-16 11:35:37.509   284   284 F DEBUG   :     #14 pc 00077dfb  /system/lib/libandroid_runtime.so (_ZN7android26NativeDisplayEventReceiver13dispatchVsyncExij+26)
08-16 11:35:37.509   284   284 F DEBUG   :     #15 pc 0007801d  /system/lib/libandroid_runtime.so (_ZN7android26NativeDisplayEventReceiver11handleEventEiiPv+80)
08-16 11:35:37.509   284   284 F DEBUG   :     #16 pc 00012f4f  /system/lib/libutils.so (_ZN7android6Looper9pollInnerEi+530)
08-16 11:35:37.509   284   284 F DEBUG   :     #17 pc 0001301f  /system/lib/libutils.so (_ZN7android6Looper8pollOnceEiPiS1_PPv+130)
08-16 11:35:37.509   284   284 F DEBUG   :     #18 pc 00083ed1  /system/lib/libandroid_runtime.so (_ZN7android18NativeMessageQueue8pollOnceEP7_JNIEnvP8_jobjecti+22)
08-16 11:35:37.509   284   284 F DEBUG   :     #19 pc 02017585  /system/framework/arm/boot.oat (offset 0x2017000)
08-16 11:35:38.485  1769 12972 W ActivityManager:   Force finishing activity com.company.debug/com.company.MainActivity
08-16 11:35:38.488   284   284 F DEBUG   :
08-16 11:35:38.488   284   284 F DEBUG   : Tombstone written to: /data/tombstones/tombstone_03
08-16 11:35:38.488   284   284 E DEBUG   : AM write failed: Broken pipe
08-16 11:35:38.491  1769  1813 I BootReceiver: Copying /data/tombstones/tombstone_03 to DropBox (SYSTEM_TOMBSTONE)
08-16 11:35:38.509  1769 12973 W DropBoxManagerService: Dropping: data_app_native_crash (2766 > 0 bytes)
08-16 11:35:38.525  1769 12972 E JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 104)
08-16 11:35:38.528  1769  1813 W DropBoxManagerService: Dropping: SYSTEM_TOMBSTONE (10 > 0 bytes)
08-16 11:35:38.541  1769 12972 W ActivityManager: Exception thrown during pause
08-16 11:35:38.541  1769 12972 W ActivityManager: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
08-16 11:35:38.541  1769 12972 W ActivityManager:   at android.os.BinderProxy.transactNative(Native Method)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at android.os.BinderProxy.transact(Binder.java:503)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at android.app.ApplicationThreadProxy.schedulePauseActivity(ApplicationThreadNative.java:734)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityStack.startPausingLocked(ActivityStack.java:866)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:2928)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityStack.finishTopRunningActivityLocked(ActivityStack.java:2784)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityStackSupervisor.finishTopRunningActivityLocked(ActivityStackSupervisor.java:2801)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityManagerService.handleAppCrashLocked(ActivityManagerService.java:12334)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityManagerService.makeAppCrashingLocked(ActivityManagerService.java:12230)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityManagerService.crashApplication(ActivityManagerService.java:12947)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:12432)
08-16 11:35:38.541  1769 12972 W ActivityManager:   at com.android.server.am.NativeCrashListener$NativeCrashReporter.run(NativeCrashListener.java:86)
08-16 11:35:38.542  1769 12972 I ActivityManager: moveHomeStack, setupComplete:true
08-16 11:35:38.549  1769  1815 E JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 60)
08-16 11:35:38.563  1769  3822 D GraphicsStats: Buffer count: 2
08-16 11:35:38.565   259   259 E lowmemorykiller: Error writing /proc/12864/oom_score_adj; errno=22
08-16 11:35:38.565  1769  5289 I WindowState: WIN DEATH: Window{912f264 u0 com.company.debug/com.company.MainActivity}
08-16 11:35:38.572   316   316 I Zygote  : Process 12864 exited due to signal (6)
08-16 11:35:38.583  1769  4299 I ActivityManager: Process com.company.debug (pid 12864) has died
08-16 11:35:38.583  1769  4299 D ActivityManager: cleanUpApplicationRecord -- 12864
08-16 11:35:38.614  1769  2912 I OpenGLRenderer: Initialized EGL, version 1.4
08-16 11:35:38.630  3817  3828 I art     : CollectorTransition marksweep + semispace GC freed 158(-356KB) AllocSpace objects, 0(0B) LOS objects, 25% free, 16MB/22MB, paused 47.182ms total 47.182ms
08-16 11:35:39.095  1769  1815 W WindowAnimator: Failed to dispatch window animation state change.
08-16 11:35:39.095  1769  1815 W WindowAnimator: android.os.DeadObjectException
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.BinderProxy.transactNative(Native Method)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.BinderProxy.transact(Binder.java:503)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.view.IWindow$Stub$Proxy.onAnimationStopped(IWindow.java:534)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at com.android.server.wm.WindowAnimator.updateWindowsLocked(WindowAnimator.java:286)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at com.android.server.wm.WindowAnimator.animateLocked(WindowAnimator.java:678)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at com.android.server.wm.WindowAnimator.-wrap0(WindowAnimator.java)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at com.android.server.wm.WindowAnimator$1.doFrame(WindowAnimator.java:123)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:856)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.view.Choreographer.doCallbacks(Choreographer.java:670)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.view.Choreographer.doFrame(Choreographer.java:603)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.Handler.handleCallback(Handler.java:746)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.Handler.dispatchMessage(Handler.java:95)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.Looper.loop(Looper.java:148)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at android.os.HandlerThread.run(HandlerThread.java:61)
08-16 11:35:39.095  1769  1815 W WindowAnimator:    at com.android.server.ServiceThread.run(ServiceThread.java:46)
08-16 11:35:39.177   261   603 I SFPerfTracer:      triggers: (rate: 0:0) (117 sw vsyncs) (0 skipped) (33:26490 vsyncs) (35:27468)
08-16 11:35:39.211  3817  4071 W OpenGLRenderer: Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
08-16 11:35:39.212  3817  4071 W OpenGLRenderer: Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
08-16 11:35:40.563   261   261 I SFPerfTracer:      triggers: (rate: 12:476) (compose: 3:63) (post: 0:22) (render: 4:81) (16:7045 frames) (17:8259)
08-16 11:35:40.563   261   261 D SFPerfTracer:        layers: (6:11) (FocusedStackFrame (0xb8b6dce8): 0:130)* (DimLayer (0xb8b70320): 0:67) (StatusBar (0xb8b2c8b8): 0:1049) (NavigationBar (0xb8b778e8): 0:473) (com.android.systemui.ImageWallpaper (0xb8b834e8): 0:164) (com.company.debug/com.company.MainActivity (0xb8b88538): 0:80)- (Application Error: com.company.debug (0xb8b7be90): 17:32) (com.google.android.googlequicksearchbox/com.google.android.launcher.GEL (0xb8b8f100): 0:5)

Reproducible Demo

This is a snippet from the application I am building. I have tested this code using a FlatList instead of a Carousel and the issue stops occurring so this might not be a react-native specific issue but rather an issue with react-native-snap-carousel

import { BANNER_DELAY, BANNER_HEIGHT, CAROUSEL_ITEM_MARGIN } from './constants';
import Carousel, { Pagination } from 'react-native-snap-carousel';
import { LayoutAnimation, NativeModules, StyleSheet, View } from 'react-native';
import React, { PureComponent } from 'react';
import { fetchMarketingBanners, fetchMarketingWidgets } from './api';

import { Colors } from '../constants';
import MarketingBanner from './MarketingBanner';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { mapLinkToButtonLabel } from './mappingFunctions';
import { marketingBannerContainerMapStateToProps } from './selectors';

const { UIManager } = NativeModules;
UIManager.setLayoutAnimationEnabledExperimental && // eslint-disable-line no-unused-expressions
  UIManager.setLayoutAnimationEnabledExperimental(true);

const expand = {
  duration: 250,
  create: LayoutAnimation.Presets.easeInEaseOut.create,
  update: LayoutAnimation.Presets.easeInEaseOut.update,
};

class MarketingBannerContainer extends PureComponent {
  componentDidMount() {
    this.refreshMarketingBanner();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.token !== this.props.token) {
      this.refreshMarketingBanner();
    }
  }

  constructor(props) {
    super(props);
    this.state = {
      activeIndex: 0,
      marketingBanners: [],
      error: null,
      loading: true,
    };

    this.handleSnapToItem = this.handleSnapToItem.bind(this);
    this.refreshMarketingBanner = this.refreshMarketingBanner.bind(this);
    this._carousel = React.createRef();
  }

  refreshMarketingBanner() {
    const { token } = this.props;
    Promise.all([fetchMarketingWidgets(token), fetchMarketingBanners(token)])
      .then(results => {
        const mediaWidgets = results[0].widget;
        const slidesData = results[1]['slides-detail'];

        const { slides: appSlidesList } = mediaWidgets.find(widget => widget.media === 'app');
        const marketingBanners = slidesData
          .filter(slide => appSlidesList.includes(slide.name))
          .sort((a, b) => appSlidesList.indexOf(a.name) - appSlidesList.indexOf(b.name));
        LayoutAnimation.configureNext(expand);
        this.setState({ marketingBanners, loading: false });
      })
      .catch(e => this.setState({ error: e.message, loading: false }));
  }

  handleSnapToItem(index) {
    this.setState({ activeIndex: index });
  }

  renderItem({ item, index }) {
    const { image_url: imageUrl, title, description, link, link_text: linkText } = item;
    const label = linkText || mapLinkToButtonLabel(link);
    const buttonLabel = label && label.toUpperCase();

    return (
      <MarketingBanner
        marketingBanner={item}
        imageUrl={imageUrl}
        title={title}
        description={description}
        link={link}
        buttonLabel={buttonLabel}
      />
    );
  }

  render() {
    const { activeIndex, marketingBanners, error, loading } = this.state;
    const { displayMarketingBanner, isTablet, width, isLandscape } = this.props;

    if (isLandscape && !isTablet) {
      return null;
    }

    if (loading || error) {
      return null;
    }

    if (!displayMarketingBanner) {
      return null;
    }

    if (Array.isArray(marketingBanners) && marketingBanners.length === 0) {
      return null;
    }

    const defaultCarouselWidth = width - 2 * CAROUSEL_ITEM_MARGIN;
    const itemWidth =  isTablet ? defaultCarouselWidth / 2 : defaultCarouselWidth;

    return (
      <View>
        <Carousel
          autoplay={true}
          autoplayDelay={BANNER_DELAY}
          autoplayInterval={BANNER_DELAY}
          data={marketingBanners}
          itemWidth={itemWidth}
          lockScrollWhileSnapping={true}
          loop={true}
          onBeforeSnapToItem={this.handleSnapToItem}
          ref={this._carousel}
          renderItem={this.renderItem}
          sliderWidth={width}
        />
        {marketingBanners.length > 1 && (
          <Pagination
            activeDotIndex={activeIndex}
            containerStyle={styles.dotContainer}
            dotsLength={marketingBanners.length}
            dotStyle={styles.dotStyle}
            inactiveDotOpacity={0.5}
            inactiveDotScale={1}
            tappableDots={false}
          />
        )}
      </View>
    );
  }
}

MarketingBannerContainer.propTypes = {
  displayMarketingBanner: PropTypes.bool,
  isLandscape: PropTypes.bool,
  isTablet: PropTypes.bool,
  token: PropTypes.string,
  width: PropTypes.number.isRequired,
};

MarketingBannerContainer.defaultProps = {
  displayMarketingBanner: true,
};

export default connect(marketingBannerContainerMapStateToProps)(MarketingBannerContainer);

const styles = StyleSheet.create({
  slide: {
    backgroundColor: Colors.row,
    height: BANNER_HEIGHT,
  },
  text: {
    color: Colors.white,
  },
  dotContainer: {
    padding: 0,
    margin: 0,
    marginTop: -20,
    marginBottom: -28,
  },
  dotStyle: {
    width: 24,
    height: 3,
    backgroundColor: Colors.white,
    marginHorizontal: -4,
  },
});
bd-arc commented 6 years ago

Hi @nar213,

Since the bug is random and you therefore don't have a reproductible example, it's quite hard to investigate, especially since I haven't encountered this issue yet.

Still, the fact that it may be an issue with the plugin rather than with the FlatList component makes me wonder if this could be the sign of an overlooked problem.

I'm currently working on replacing the FlatList component altogether (see #250); hopefully this will help solving the issue!

dohooo commented 3 years ago

Sorry, please allow me to advertise for my open source library! ~ I think this library react-native-reanimated-carousel will solve your problem. It is a high performance and very simple component, complete with React-Native reanimated 2