Jetpack Compose与View框架混编出现IR lowering编译错误
问题
在基于View框架开发的Activity中,尝试用Jetpack Compose展示Snackbar。需求是当应用处于后台时,用户点击DeepLink触发显示该Snackbar,但编译失败,抛出Backend Internal error: Exception during IR lowering错误,堆栈信息显示生成onNewIntent方法代码时出现异常,具体错误栈如下:
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:50) at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:239) at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:235) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:68) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:55) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:41) at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96) at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29) at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96) at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29) at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96) at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43) at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.doGenerateFilesInternal(JvmIrCodegenFactory.kt:195) at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:60) at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:35) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:331) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:123) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:58) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:92) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:434) at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:120) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:357) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally$default(IncrementalCompilerRunner.kt:299) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:159) at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:80) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:622) at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:100) at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1713) at jdk.internal.reflect.GeneratedMethodAccessor114.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359) at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829)
根因:
java.lang.RuntimeException: Exception while generating code for: FUN name:onNewIntent
解决方案
- 检查Kotlin与Compose版本兼容性:这类IR代码生成错误大多源于版本不匹配,确保项目中Kotlin版本和Compose Compiler版本严格对应,比如Kotlin 1.8.20对应Compose Compiler 1.4.7,Kotlin 1.9.0对应Compose Compiler 1.5.0。
- 重构
onNewIntent中的Compose调用逻辑:不要在onNewIntent中直接操作Compose状态或调用Snackbar,通过中间状态传递实现:- 在Activity中定义
MutableState<Boolean>标记是否显示Snackbar; - 在
onNewIntent中更新该标记; - 在Compose的
setContent块中监听标记,触发Snackbar显示并在合适时机重置标记。
示例代码:
class MyViewActivity : AppCompatActivity() { private val showSnackbar = mutableStateOf(false) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyTheme { // 原有View与Compose整合代码 if (showSnackbar.value) { Snackbar( action = { Button(onClick = { showSnackbar.value = false }) { Text("关闭") } } ) { Text("DeepLink触发的提示") } // 自动隐藏并重置标记 LaunchedEffect(Unit) { delay(3000) showSnackbar.value = false } } } } } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) // 处理DeepLink逻辑后更新标记 showSnackbar.value = true } } - 在Activity中定义
- 清理缓存重新编译:通过Android Studio的
File -> Invalidate Caches... -> Invalidate and Restart清除构建缓存,再重新编译项目,排除缓存导致的异常。 - 避免在View生命周期方法中直接调用Compose API:
onNewIntent属于View体系生命周期方法,直接调用Compose相关逻辑容易触发编译器IR生成bug,通过状态中转是更安全的实现方式。
内容的提问来源于stack exchange,提问作者Regress.arg
相关产品推荐
相关产品推荐

