EnterTransitionCoordinator 在 Android 5.0 中导致 NPE
EnterTransitionCoordinator causes NPE in Android 5.0
添加退出并进入 Activity 转换到应用后,我收到如下崩溃报告:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke
virtual method 'android.view.ViewParent android.view.View.getParent()'
on a null object reference
at android.view.ViewOverlay$OverlayViewGroup.add(ViewOverlay.java:164)
at android.view.ViewGroupOverlay.add(ViewGroupOverlay.java:63)
at android.app.EnterTransitionCoordinator.startRejectedAnimations(EnterTransitionCoordinator.java:598)
at android.app.EnterTransitionCoordinator.startSharedElementTransition(EnterTransitionCoordinator.java:325)
at android.app.EnterTransitionCoordinator.access0(EnterTransitionCoordinator.java:42)
at android.app.EnterTransitionCoordinator.run(EnterTransitionCoordinator.java:389)
at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:698)
at android.app.EnterTransitionCoordinator.onPreDraw(EnterTransitionCoordinator.java:386)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1985)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5845)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5272)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
它不可重现,但崩溃次数很重要。
做一些研究,我发现这个提交表明它是(实际上)Android 中的一个内部错误:
https://android.googlesource.com/platform/frameworks/base/+/83c692efd3c53050fce132dfd2ef21763d3cf010%5E%21/#F0
所有崩溃报告都是 5.0、5.0.1 或 5.0.2。因为 5.1 传播范围更广,但没有显示崩溃,似乎 EnterTransitionCoordinator 在 5.1 中得到了修复。
因此,一个可能的解决方案是检查 API 级别 22 或更高级别,然后只进行转换。但是我想知道是否有更好的方法;可能有一些解决方法,尽管这似乎是 Android 的内部问题(堆栈中的所有系统 类)?
对于低于 API 的 5.1,使用 postponeEnterTransition()
推迟共享元素转换。将侦听器 OnDrawListener
注册到装饰视图(可能)或内容视图(android.R.id.content
)的 ViewTreeObserver
并在调用 onDraw()
后开始转换。一旦开始转换,不要忘记注销监听器。
要求 API 级别 22 (Android 5.1) 进行转换后,崩溃问题消失了。所以这是最简单的解决方案。如果您需要使用 Android 5.0 来支持它,请查看 Nikola 的回答(我们没有自己尝试以避免额外的代码)。
此 Android OS 错误与共享元素转换期间 'rejected' 元素的处理有关。如果共享元素未附加到 window,则共享元素将被拒绝(从转换中排除),这可能是因为其可见性设置为 GONE
.
我使用的解决方法是在调用 makeSceneTransitionAnimation()
之前检查每个潜在的共享元素视图,并且仅当其可见性设置为 VISIBLE
.[=13= 时才将其包含在列表中]
添加退出并进入 Activity 转换到应用后,我收到如下崩溃报告:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewParent android.view.View.getParent()' on a null object reference at android.view.ViewOverlay$OverlayViewGroup.add(ViewOverlay.java:164) at android.view.ViewGroupOverlay.add(ViewGroupOverlay.java:63) at android.app.EnterTransitionCoordinator.startRejectedAnimations(EnterTransitionCoordinator.java:598) at android.app.EnterTransitionCoordinator.startSharedElementTransition(EnterTransitionCoordinator.java:325) at android.app.EnterTransitionCoordinator.access0(EnterTransitionCoordinator.java:42) at android.app.EnterTransitionCoordinator.run(EnterTransitionCoordinator.java:389) at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:698) at android.app.EnterTransitionCoordinator.onPreDraw(EnterTransitionCoordinator.java:386) at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1985) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1077) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5845) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:550) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5272) at java.lang.reflect.Method.invoke(Method.java) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
它不可重现,但崩溃次数很重要。
做一些研究,我发现这个提交表明它是(实际上)Android 中的一个内部错误: https://android.googlesource.com/platform/frameworks/base/+/83c692efd3c53050fce132dfd2ef21763d3cf010%5E%21/#F0
所有崩溃报告都是 5.0、5.0.1 或 5.0.2。因为 5.1 传播范围更广,但没有显示崩溃,似乎 EnterTransitionCoordinator 在 5.1 中得到了修复。
因此,一个可能的解决方案是检查 API 级别 22 或更高级别,然后只进行转换。但是我想知道是否有更好的方法;可能有一些解决方法,尽管这似乎是 Android 的内部问题(堆栈中的所有系统 类)?
对于低于 API 的 5.1,使用 postponeEnterTransition()
推迟共享元素转换。将侦听器 OnDrawListener
注册到装饰视图(可能)或内容视图(android.R.id.content
)的 ViewTreeObserver
并在调用 onDraw()
后开始转换。一旦开始转换,不要忘记注销监听器。
要求 API 级别 22 (Android 5.1) 进行转换后,崩溃问题消失了。所以这是最简单的解决方案。如果您需要使用 Android 5.0 来支持它,请查看 Nikola 的回答(我们没有自己尝试以避免额外的代码)。
此 Android OS 错误与共享元素转换期间 'rejected' 元素的处理有关。如果共享元素未附加到 window,则共享元素将被拒绝(从转换中排除),这可能是因为其可见性设置为 GONE
.
我使用的解决方法是在调用 makeSceneTransitionAnimation()
之前检查每个潜在的共享元素视图,并且仅当其可见性设置为 VISIBLE
.[=13= 时才将其包含在列表中]