跨模块通过Hilt注入含Composable方法的接口实现时触发kotlin.NotImplementedError编译错误
跨模块通过Hilt注入含Composable方法的接口实现时触发kotlin.NotImplementedError编译错误
这个问题我之前踩过坑!本质是Compose编译器在处理跨模块接口中的@Composable方法时,无法正确追踪到实现类的Composable元数据导致的——Compose的@Composable注解依赖编译期生成的上下文信息,而接口的抽象调用会让跨模块的编译器丢失这些关键信息,从而抛出这个看似“未实现”的错误(其实不是真的没实现,是编译器识别不了)。
下面给你几个可行的解决方案,按推荐优先级排序:
方案一:用抽象类替代接口
把原来的接口改成抽象类,Compose编译器对抽象类的继承关系处理更友好,能正确识别跨模块的Composable方法:
// 模块A的抽象类 abstract class AInterface { @Composable abstract fun Show(modifier: Modifier = Modifier) } class AInterfaceImpl : AInterface() { @Composable override fun Show(modifier: Modifier) { Text( modifier = modifier, text = "Message", ) } }
Hilt的注入逻辑不需要改动,模块B中调用的代码也完全不变,这样编译错误应该就能消失了。
方案二:调整接口设计,解耦Composable渲染
如果不想改用抽象类,可以把接口的职责从直接提供Composable渲染,改成提供渲染所需的数据/逻辑,让调用方的Composable负责实际渲染:
// 模块A的接口 interface AInterface { fun getDisplayContent(): String } class AInterfaceImpl : AInterface { override fun getDisplayContent(): String = "Message" }
模块B的Composable调用:
@Composable fun ShowAInterfaceImpl( modifier: Modifier, aInterface: AInterface ) { Text( modifier = modifier, text = aInterface.getDisplayContent() ) }
这种方式彻底避开了跨模块接口调用Composable的问题,还能让业务逻辑和UI渲染解耦,是更推荐的长期方案。
方案三:临时 workaround(不推荐)
如果只是临时测试需要,可以在模块B中把注入的接口实例强制转换成实现类再调用,但这会破坏接口的抽象性,让模块B直接依赖模块A的实现类,耦合度很高,不建议用于生产环境:
@Composable fun ShowAInterfaceImpl( modifier: Modifier, aInterface: AInterface ) { (aInterface as AInterfaceImpl).Show( modifier = modifier ) }
你可以先试试方案一,应该能快速解决问题;如果项目架构不允许改接口为抽象类,方案二是更合理的重构方向。
备注:内容来源于stack exchange,提问作者mooongcle
相关产品推荐
相关产品推荐

