Android模拟器切换屏幕尺寸时出现ClassCastException问题求助
Android模拟器切换屏幕尺寸时的ClassCastException问题分析
问题场景与异常信息
在Android模拟器中使用Resizable API(VanillaIceCreame)切换平板、折叠屏、手机等不同屏幕尺寸时,触发如下ClassCastException异常:
java.lang.ClassCastException: androidx.compose.foundation.layout.ConsumedInsetsModifier cannot be cast to androidx.compose.ui.input.pointer.PointerInputModifier at androidx.compose.ui.node.BackwardsCompatNode.onCancelPointerInput(BackwardsCompatNode.kt:354) at androidx.compose.ui.node.PointerInputModifierNode.onDensityChange(PointerInputModifierNode.kt:102) at androidx.compose.ui.node.LayoutNode.setDensity(LayoutNode.kt:669) at androidx.compose.ui.node.LayoutNode.setCompositionLocalMap(LayoutNode.kt:696) at androidx.compose.ui.node.ComposeUiNode$Companion$SetResolvedCompositionLocals$1.invoke(ComposeUiNode.kt:44) at androidx.compose.ui.node.ComposeUiNode$Companion$SetResolvedCompositionLocals$1.invoke(ComposeUiNode.kt:43) at androidx.compose.runtime.Applier.apply(Applier.kt:180) at androidx.compose.runtime.changelist.Operation$UpdateNode.execute(Operation.kt:554) at androidx.compose.runtime.changelist.Operations.executeAndFlushAllPendingOperations(Operations.kt:332) at androidx.compose.runtime.changelist.ChangeList.executeAndFlushAllPendingChanges(ChangeList.kt:88) at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:1033) at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1064) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:669) at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:576) at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:39) at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:108) at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1404) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415) at android.view.Choreographer.doCallbacks(Choreographer.java:1015) at android.view.Choreographer.doFrame(Choreographer.java:941) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389) at android.os.Handler.handleCallback(Handler.java:959) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loopOnce(Looper.java:232) at android.os.Looper.loop(Looper.java:317) at android.app.ActivityThread.main(ActivityThread.java:8674) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@8f5b374, androidx.compose.ui.platform.MotionDurationScaleImpl@d02f09d, StandaloneCoroutine{Cancelling}@5fe7912, AndroidUiDispatcher@c2938e3]
当前使用的开发环境:
Android Studio Ladybug | 2024.2.1 Patch 2 Build #AI-242.23339.11.2421.12550806, built on October 24, 2024 Runtime version: 21.0.3+-79915917-b509.11 aarch64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Toolkit: sun.lwawt.macosx.LWCToolkit macOS 15.1 GC: G1 Young Generation, G1 Concurrent GC, G1 Old Generation Memory: 4096M Cores: 8 Metal Rendering is ON Registry: ide.instant.shutdown=false debugger.new.tool.window.layout=true ide.experimental.ui=true i18n.locale= terminal.new.ui=true Non-Bundled Plugins: com.intellij.marketplace (242.22855.133) dev.j-a.swift (1.1.0.354-242) tarn.gradle.dependencies (2.0.0) com.jetbrains.kmm (0.8.3(242)-5)
旧版Android Studio中无此问题,且错误栈未涉及业务代码,排除业务代码导致的可能。
问题根源
这个问题是Compose UI库内部的兼容性Bug,具体触发逻辑如下:
- 切换屏幕尺寸时,系统会更新布局节点(
LayoutNode)的密度(Density)参数; - 密度变更会触发
PointerInputModifierNode的onDensityChange回调; - 该回调内部调用了
BackwardsCompatNode的onCancelPointerInput方法; - 在这个方法中,错误地将
ConsumedInsetsModifier(用于处理布局内边距的Modifier)强制转换为PointerInputModifier(用于处理指针输入事件的Modifier),两者属于完全不同的Modifier类型体系,因此抛出ClassCastException。
此问题与升级到Android Studio Ladybug版本直接相关,新版AS默认绑定的Compose UI库版本引入了这个兼容性缺陷,而旧版AS对应的Compose版本不存在该问题。
内容的提问来源于stack exchange,提问作者Mark Delphi
相关产品推荐
相关产品推荐

