Android Jetpack Compose能否仅在debug构建类型中启用?
能否仅在debug构建类型中启用Jetpack Compose?
原始配置尝试
我最初设想在build.gradle中按如下方式配置,只在debug版本中开启Compose能力:
android { buildTypes { debug { ... buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion = composeCompilerVersion } } release { buildFeatures { compose false } } } } dependencies { debugImplementation "androidx.compose.ui:ui:$composeVersion" debugImplementation "androidx.compose.material:material:$composeVersion" debugImplementation "androidx.compose.ui:ui-tooling:$composeVersion" debugImplementation "com.google.android.material:compose-theme-adapter:$composeVersion" debugImplementation "androidx.compose.runtime:runtime-livedata:$composeVersion" debugImplementation "androidx.compose.compiler:compiler:$composeCompilerVersion" debugImplementation 'androidx.activity:activity-compose:1.3.1' }
遇到的错误
上述配置无法通过编译,执行./gradlew assembleDebug命令时抛出java.lang.IllegalStateException: couldn't find inline method Landroidx/compose/runtime/ComposablesKt;.remember异常,完整错误栈如下:
org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering File being compiled: /Users/BruceWayne/AndroidStudioProjects/Libon/android-libon-lite/libon-lite-client/src/debug/kotlin/com/libon/lite/debug/CallLogDebugActivity.kt 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) Caused by: java.lang.RuntimeException: Exception while generating code for: FUN name:FillCallLog visibility:private modality:FINAL <> ($this:com.libon.lite.debug.CallLogDebugActivity) returnType:kotlin.Unit annotations: Composable $this: VALUE_PARAMETER name:<this> type:com.libon.lite.debug.CallLogDebugActivity BLOCK_BODY VAR name:snackbarHostState type:androidx.compose.material.SnackbarHostState [val] CALL 'public final fun remember <T> (calculation: @[DisallowComposableCalls] kotlin.Function0<T of androidx.compose.runtime.ComposablesKt.remember>): T of androidx.compose.runtime.ComposablesKt.remember [inline] declared in androidx.compose.runtime.ComposablesKt' type=androidx.compose.material.SnackbarHostState origin=null <T>: androidx.compose.material.SnackbarHostState calculation: BLOCK type=kotlin.Function0<androidx.compose.material.SnackbarHostState> origin=LAMBDA COMPOSITE type=kotlin.Unit origin=null FUNCTION_REFERENCE 'private final fun FillCallLog$lambda-1 (): androidx.compose.material.SnackbarHostState declared in com.libon.lite.debug.CallLogDebugActivity' type=kotlin.Function0<androidx.compose.material.SnackbarHostState> origin=LAMBDA reflectionTarget=null CALL 'public final fun Column$default (modifier: androidx.compose.ui.Modifier?, verticalArrangement: androidx.compose.foundation.layout.Arrangement.Vertical?, horizontalAlignment: androidx.compose.ui.Alignment.Horizontal?, content: @[Composable] @[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit>, $mask0: kotlin.Int, $handler: kotlin.Any?): kotlin.Unit [inline] declared in androidx.compose.foundation.layout.ColumnKt' type=kotlin.Unit origin=DEFAULT_DISPATCH_CALL modifier: COMPOSITE type=androidx.compose.ui.Modifier? origin=DEFAULT_VALUE CONST Null type=androidx.compose.ui.Modifier? value=null verticalArrangement: COMPOSITE type=androidx.compose.foundation.layout.Arrangement.Vertical? origin=DEFAULT_VALUE CONST Null type=androidx.compose.foundation.layout.Arrangement.Vertical? value=null horizontalAlignment: COMPOSITE type=androidx.compose.ui.Alignment.Horizontal? origin=DEFAULT_VALUE CONST Null type=androidx.compose.ui.Alignment.Horizontal? value=null content: BLOCK type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=LAMBDA COMPOSITE type=kotlin.Unit origin=null FUNCTION_REFERENCE 'private final fun FillCallLog$lambda-2 (this$0: com.libon.lite.debug.CallLogDebugActivity, $snackbarHostState: androidx.compose.material.SnackbarHostState): kotlin.Unit declared in com.libon.lite.debug.CallLogDebugActivity' type=@[ExtensionFunctionType] kotlin.Function1<androidx.compose.foundation.layout.ColumnScope, kotlin.Unit> origin=LAMBDA reflectionTarget=null this$0: GET_VAR '<this>: com.libon.lite.debug.CallLogDebugActivity declared in com.libon.lite.debug.CallLogDebugActivity.FillCallLog' type=com.libon.lite.debug.CallLogDebugActivity origin=null $snackbarHostState: GET_VAR 'val snackbarHostState: androidx.compose.material.SnackbarHostState [val] declared in com.libon.lite.debug.CallLogDebugActivity.FillCallLog' type=androidx.compose.material.SnackbarHostState origin=null $mask0: CONST Int type=kotlin.Int value=7 $handler: CONST Null type=kotlin.Any? value=null CALL 'public final fun SnackbarHost$default (hostState: androidx.compose.material.SnackbarHostState, modifier: androidx.compose.ui.Modifier?, snackbar: @[Composable] kotlin.Function1<androidx.compose.material.SnackbarData, kotlin.Unit>?, $mask0: kotlin.Int, $handler: kotlin.Any?): kotlin.Unit declared in androidx.compose.material.SnackbarHostKt' type=kotlin.Unit origin=DEFAULT_DISPATCH_CALL hostState: GET_VAR 'val snackbarHostState: androidx.compose.material.SnackbarHostState [val] declared in com.libon.lite.debug.CallLogDebugActivity.FillCallLog' type=androidx.compose.material.SnackbarHostState origin=null modifier: COMPOSITE type=androidx.compose.ui.Modifier? origin=DEFAULT_VALUE CONST Null type=androidx.compose.ui.Modifier? value=null snackbar: COMPOSITE type=@[Composable] kotlin.Function1<androidx.compose.material.SnackbarData, kotlin.Unit>? origin=DEFAULT_VALUE CONST Null type=@[Composable] kotlin.Function1<androidx.compose.material.SnackbarData, kotlin.Unit>? value=null $mask0: CONST Int type=kotlin.Int value=6 $handler: CONST Null type=kotlin.Any? value=null at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:50) Caused by: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call: CALL 'public final fun remember <T> (calculation: @[DisallowComposableCalls] kotlin.Function0<T of androidx.compose.runtime.ComposablesKt.remember>): T of androidx.compose.runtime.ComposablesKt.remember [inline] declared in androidx.compose.runtime.ComposablesKt' type=androidx.compose.material.SnackbarHostState origin=null Method: null File is unknown The root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:109) Caused by: java.lang.IllegalStateException: couldn't find inline method Landroidx/compose/runtime/ComposablesKt;.remember(Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.getMethodNode(SourceCompilerForInline.kt:109) at org.jetbrains.kotlin.codegen.inline.SourceCompilerForInlineKt.loadCompiledInlineFunction(SourceCompilerForInline.kt:86) at org.jetbrains.kotlin.backend.jvm.codegen.IrSourceCompilerForInline.compileInlineFunction(IrSourceCompilerForInline.kt:89) at org.jetbrains.kotlin.codegen.inline.InlineCodegen.performInline(InlineCodegen.kt:48) ... 70 more
问题根因
buildFeatures.compose是项目全局配置项,不支持放在buildTypes下针对不同构建类型单独配置,写在构建类型内部的compose开关不会生效。上述错误就是因为compose编译器插件没有被全局启用,导致编译时无法识别Compose的注解和内联函数,找不到对应的核心方法。
可行实现方案
如果要实现release包完全不包含Compose相关代码和依赖,可按如下方式配置:
- 全局开启Compose开关,配置compose编译器版本,这个操作只会增加编译耗时,不会往release包中打入任何额外代码
- 所有Compose相关依赖全部使用
debugImplementation引入,确保release构建时不会引入Compose依赖库 - 所有使用Compose的代码,包括Activity、自定义组件等,全部放在
src/debug目录下,src/main和src/release目录中不要出现任何对Compose API的引用
正确配置示例如下:
android { // 全局开启compose开关 buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion = composeCompilerVersion } buildTypes { debug { // debug构建的其他配置 ... } release { // release构建的其他配置 ... } } } dependencies { // 所有compose依赖全用debugImplementation debugImplementation "androidx.compose.ui:ui:$composeVersion" debugImplementation "androidx.compose.material:material:$composeVersion" debugImplementation "androidx.compose.ui:ui-tooling:$composeVersion" debugImplementation "com.google.android.material:compose-theme-adapter:$composeVersion" debugImplementation "androidx.compose.runtime:runtime-livedata:$composeVersion" debugImplementation 'androidx.activity:activity-compose:1.3.1' }
按上述配置实现后,release包不会包含任何Compose相关的代码和依赖,和完全不接入Compose的包体积一致,debug包则可以正常使用Compose能力。
内容的提问来源于stack exchange,提问作者Florang
相关产品推荐
相关产品推荐

