Kotlin Compose中如何判断空block并解决Composable调用报错
问题根因
- 第一版代码逻辑失效:Kotlin里的lambda是匿名类实例,
block == {}的判断永远返回false。等号两边是两个独立创建的空lambda对象,哪怕逻辑完全一致,引用相等校验也不会通过,所以默认打开链接的分支永远走不到。 - 第二版代码编译报错:
LocalUriHandler.current是Composable专属API,只能在Composable上下文里调用,但函数参数的默认值执行位置不属于Composable上下文,直接在这里调用就会触发*@Composable invocations can only happen from the context of a @Composable function*报错。
正确实现
用可空类型的block参数做判断,把LocalUriHandler的获取放在Composable函数体内部,不要放在参数默认值里:
@Composable fun AnnotatedURLText( // 其余原有参数保持不变 block: ((String) -> Unit)? = null ) { val uriHandler = LocalUriHandler.current // 其余原有逻辑,比如annotatedText构建等保持不变 ClickableText( // 其余原有参数保持不变 onClick = { offset -> annotatedText.getStringAnnotations( tag = "URL", start = offset, end = offset ).firstOrNull()?.let { annotation -> if (block != null) { // 传入了自定义处理逻辑就执行自定义逻辑 block(annotation.item) } else { // 没传自定义逻辑就走默认打开链接的行为 uriHandler.openUri(annotation.item) } } } ) }
三种调用场景的实际表现
- 调用方式A(传入自定义逻辑):点击链接时执行传入的
todo()逻辑,符合预期AnnotatedURLText(/* 其他参数 */) { url -> todo(url) } - 调用方式B(不传block参数):点击链接时默认调用
uriHandler.openUri打开对应地址,符合预期AnnotatedURLText(/* 其他参数 */) - 调用方式C(传入空实现block):点击链接时执行空逻辑,无任何操作,符合“显式传入自定义逻辑优先”的设计规则
AnnotatedURLText(/* 其他参数 */) { }
如果你需要实现“哪怕用户传入空lambda,也执行默认打开逻辑”的效果,不建议靠判断lambda是否为空来实现,应该额外增加一个控制参数比如
useDefaultUriHandler: Boolean = true做显式控制,避免出现预期外的逻辑分支。
内容的提问来源于stack exchange,提问作者HelloCW
相关产品推荐
相关产品推荐

