使用 LayoutAnimationController.shouldAnimateLayout 反应原生 Android 崩溃
Posted
技术标签:
【中文标题】使用 LayoutAnimationController.shouldAnimateLayout 反应原生 Android 崩溃【英文标题】:React Native Android crash with LayoutAnimationController.shouldAnimateLayout 【发布时间】:2020-09-10 09:20:41 【问题描述】:我的应用在 android 设备上的生产模式下崩溃。基本上它发生在 Android 10(三星、小米、华为、LGE)上。
堆栈跟踪
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewParent android.view.View.getParent()' on a null object reference
at com.facebook.react.uimanager.layoutanimation.LayoutAnimationController.shouldAnimateLayout (LayoutAnimationController.java:91)
at com.facebook.react.uimanager.NativeViewHierarchyManager.manageChildren(NativeViewHierarchyManager.java:453)
atcom.facebook.react.uimanager.UIViewOperationQueue$ManageChildrenOperation.execute(UIViewOperationQueue.java:206)
at com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:792)
at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:903)
at com.facebook.react.uimanager.UIViewOperationQueue.access$2400(UIViewOperationQueue.java:43)
at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:963)
at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:997)
at android.view.Choreographer.doCallbacks(Choreographer.java:797)
at android.view.Choreographer.doFrame(Choreographer.java:728)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:984)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8016)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
React Native 版本:
System:
OS: macOS 10.15.4
CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
Memory: 405.76 MB / 8.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 13.13.0 - /usr/local/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.5 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.9.1 - /usr/local/bin/pod
SDKs:
ios SDK:
Platforms: iOS 13.7, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API Levels: 28, 29
Build Tools: 28.0.3, 29.0.0, 29.0.2, 29.0.3
System Images: android-22 | Google APIs Intel x86 Atom, android-24 | Google APIs Intel x86 Atom, android-24 | Google Play Intel x86 Atom, android-26 | Google Play Intel x86 Atom, android-29 | Google Play Intel x86 Atom, android-30 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6514223
Xcode: 11.7/11E801a - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_242-release - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.0 => 0.62.0
npmGlobalPackages:
*react-native*: Not Found
我有带有动画变量的文件:
import LayoutAnimation, LayoutAnimationConfig from 'react-native';
export const AnimationVars =
layoutAnimation:
keyboard,
expandCollapse: ...LayoutAnimation.Presets.easeInEaseOut, duration: expandCollapseDuration as LayoutAnimationConfig,
inputField: ...LayoutAnimation.Presets.easeInEaseOut, duration: inputFieldDuration as LayoutAnimationConfig,
dialogTransform: ...LayoutAnimation.Presets.easeInEaseOut, duration: expandCollapseDuration as LayoutAnimationConfig,
navBarTransform: ...LayoutAnimation.Presets.easeInEaseOut, duration: navBarDuration as LayoutAnimationConfig,
,
;
在我的应用程序的不同位置使用 var 之后,例如在切换方法中的 TitleExpanding 组件中:
private _onToggle(nextValue: boolean, animate: boolean = true)
const rotateValue = !nextValue ? 1 : 0;
if (animate)
requestAnimationFrame(() =>
timing(this._rotateValue,
toValue: rotateValue,
duration: AnimationVars.expandCollapseDuration,
easing: Easing.linear,
).start();
);
LayoutAnimation.configureNext(AnimationVars.layoutAnimation.expandCollapse);
else
this._rotateValue.setValue(rotateValue);
this._toggle.toggle();
const preferencesKey = this.props.preferencesKey;
if (preferencesKey)
this._preferences.set(preferencesKey, nextValue ? 'false' : 'true').then();
我认为这是类似的问题https://github.com/facebook/react-native/issues/25832。如果有人遇到同样的错误,请告诉我。
【问题讨论】:
【参考方案1】:我遇到了一个类似的问题,它围绕着我旋转,有一个带有按钮的 Modal 可以触发 LayoutAnimation
。我发现的一种解决方案是将LayoutAnimation.configureNext
包装在setImmediate
中,例如
setImmediate(() => LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut));
这具有在执行操作之前允许模态足够的时间来移除的效果。
【讨论】:
以上是关于使用 LayoutAnimationController.shouldAnimateLayout 反应原生 Android 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)