callstack / react-native-slider

React Native component exposing Slider from iOS and SeekBar from Android
MIT License
1.19k stars 267 forks source link

ReactSlider crash on Android release version #9

Closed cpojer closed 4 years ago

cpojer commented 5 years ago

This issue was originally created by @ssg-luke as facebook/react-native#9979.


Issue Description

Hard crash randomly and unexpectedly on Android release version only (debug is fine, iOS is fine on both debug and release) when hiding and displaying sliders based on a state variable.

Steps to Reproduce / Code Snippets

We have a number of photo filters in our app which are selected by <TouchableOpacity> components and some have a slider to adjust the blur or brightness etc. These sliders are completely separate from each other and are displayed based on a string stored in the components state called filter.

Here is one such slider from render():

`{filter === 'gamify' && (

How retro do you want to go? this.setState({pixelSize: value})} /> )}` #### Expected Results No crash when hiding and displaying sliders ### Stack Trace java.lang.NullPointerException: Attempt to write to field 'java.util.ArrayList android.animation.AnimatorSet$Node.nodeDependents' on a null object reference http://pastebin.com/270Wg6Pu ### Additional Information - React Native version: 0.33 - Platform(s) (iOS, Android, or both?): Android (Release only) - Operating System (macOS, Linux, or Windows?): Mac OSX
cinder92 commented 5 years ago

any update on this?

troZee commented 5 years ago

@cinder92 still exist

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.ptrocki, PID: 25728
    java.lang.IllegalStateException: Circular dependencies cannot exist in AnimatorSet
        at android.animation.AnimatorSet.sortNodes(AnimatorSet.java:922)
        at android.animation.AnimatorSet.start(AnimatorSet.java:540)
        at android.animation.AnimatorSet.start(AnimatorSet.java:586)
        at android.graphics.drawable.AnimatedVectorDrawable.start(AnimatedVectorDrawable.java:599)
        at android.graphics.drawable.AnimatedStateListDrawable$AnimatedVectorDrawableTransition.start(AnimatedStateListDrawable.java:339)
        at android.graphics.drawable.AnimatedStateListDrawable.selectTransition(AnimatedStateListDrawable.java:226)
        at android.graphics.drawable.AnimatedStateListDrawable.onStateChange(AnimatedStateListDrawable.java:146)
        at android.graphics.drawable.Drawable.setState(Drawable.java:685)
        at android.widget.AbsSeekBar.drawableStateChanged(AbsSeekBar.java:378)
        at android.support.v7.widget.AppCompatSeekBar.drawableStateChanged(AppCompatSeekBar.java:61)
        at android.view.View.refreshDrawableState(View.java:17433)
        at android.view.View.setPressed(View.java:8045)
        at android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:595)
        at android.view.View.dispatchTouchEvent(View.java:9490)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2666)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
        at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2454)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1773)
        at android.app.Activity.dispatchTouchEvent(Activity.java:2798)
        at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2415)
        at android.view.View.dispatchPointerEvent(View.java:9721)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4738)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4596)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4266)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4323)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4154)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4120)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4128)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4101)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6555)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6529)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6472)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6727)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
        at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
        at android.view.InputEventReceiver.consumeBatchedInputEvents(Inpu
Sugarya commented 5 years ago

I also have a similar bug with react-native 0.57.8. I use another slider (https://github.com/jeanregisser/react-native-slider) instead of the slider of React Native component, and It does work! 57E4767E-A811-bug-desc

MBach commented 5 years ago

According to Crashlytics, I just had this NullPointerException on Android 6.0 and Huawei Y6II

BAE86AEC1946B6AB60CCD7452DC811F0 commented 4 years ago

I also have a similar bug with react-native 0.61.5. any update on this?

java.lang.NullPointerException: Attempt to write to field 'java.util.ArrayList android.animation.AnimatorSet$Node.nodeDependents' on a null object reference
    at android.animation.AnimatorSet.clone(AnimatorSet.java:700)
    at android.animation.AnimatorSet.clone(AnimatorSet.java:51)
    at android.animation.Animator$AnimatorConstantState.newInstance(Animator.java:562)
    at android.animation.Animator$AnimatorConstantState.newInstance(Animator.java:543)
    at android.content.res.ConstantState.newInstance(ConstantState.java:51)
    at android.content.res.ConstantState.newInstance(ConstantState.java:59)
    at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:133)
    at android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator.newInstance(AnimatedVectorDrawable.java:567)
    at android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState.inflatePendingAnimators(AnimatedVectorDrawable.java:545)
    at android.graphics.drawable.AnimatedVectorDrawable.applyTheme(AnimatedVectorDrawable.java:377)
    at android.graphics.drawable.DrawableContainer$DrawableContainerState.applyTheme(DrawableContainer.java:865)
    at android.graphics.drawable.DrawableContainer.applyTheme(DrawableContainer.java:577)
    at android.graphics.drawable.StateListDrawable.applyTheme(StateListDrawable.java:370)
    at android.graphics.drawable.AnimatedStateListDrawable.applyTheme(AnimatedStateListDrawable.java:391)
    at android.content.res.Resources.loadDrawable(Resources.java:2615)
    at android.content.res.VivoResources.loadDrawable(VivoResources.java:220)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
    at android.widget.AbsSeekBar.<init>(AbsSeekBar.java:95)
    at android.widget.SeekBar.<init>(SeekBar.java:85)
    at android.widget.SeekBar.<init>(SeekBar.java:81)
    at androidx.appcompat.widget.AppCompatSeekBar.<init>(AppCompatSeekBar.java:47)
    at com.reactnativecommunity.slider.ReactSlider.<init>(ReactSlider.java:68)
    at com.reactnativecommunity.slider.ReactSliderManager.createViewInstance(ReactSliderManager.java:129)
    at com.reactnativecommunity.slider.ReactSliderManager.createViewInstance(ReactSliderManager.java:40)
    at com.facebook.react.uimanager.ViewManager.createViewInstance(ViewManager.java:139)
    at com.facebook.react.uimanager.ViewManager.createView(ViewManager.java:82)
    at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:269)
    at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:179)
    at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.dispatchPendingNonBatchedOperations(UIViewOperationQueue.java:972)
    at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:943)
    at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:28)
    at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:174)
    at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:84)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:890)
    at android.view.Choreographer.doCallbacks(Choreographer.java:704)
    at android.view.Choreographer.doFrame(Choreographer.java:637)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:878)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5619)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)
newyankeecodeshop commented 3 years ago

I believe the crash is caused by the custom Yoga measure implementation here: https://github.com/callstack/react-native-slider/blob/45c2a5438f0d7e2dd586a663c4043e795d6c1761/src/android/src/main/java/com/reactnativecommunity/slider/ReactSliderManager.java#L69

That code runs on the Yoga layout thread, but it allocates a ReactSlider view. Since ReactSlider extends Android SeekBar, the constructor runs animation and drawable code on different thread than the main thread. I suspect this low-level Android view code is not thread-safe, and not designed to be run on a thread that is not the main thread.

To prevent this code from executing, I changed the style for our <ReactSlider> to include a specific width and height. This prevents Yoga from needing to measure the view. The crash no longer happens for our app.

const style = { height: 40, width: "100%" }

<ReactSlider style={style} ... />

Hope this helps!

P.S. - I don't know enough about Android view drawing and measurement to know how to implement the measure method without allocating a slider view. Maybe the measure could allocate the view on the main thread and block until that finishes?