如何用Hilt向Composable注入普通Kotlin类?替代ViewModel咨询
解决方案整理
一、基于Hilt的解决思路
不用把普通逻辑类注入到Activity,而是在Composable内部通过Hilt获取依赖,再用remember绑定实例与Composable的生命周期:
- 确保你的Activity已标记为
@AndroidEntryPoint - 在Composable中直接通过
hilt()函数获取所需依赖(比如Repository),创建普通逻辑类实例后用remember包裹:
@Composable fun MyFeatureScreen() { // 通过Hilt获取Repository依赖 val userRepository = hilt<UserRepository>() // 用remember绑定逻辑类实例与Composable生命周期,退出组合时实例会被回收 val userLogic = remember { UserLogic(userRepository) } // 后续使用userLogic处理UI逻辑 }
这种方式既利用了Hilt的依赖注入能力,又保证逻辑类的生命周期和Composable绑定,不会在Composable退出后残留。
如果你的逻辑类本身需要多个注入依赖,可给它添加@Inject构造函数,直接通过hilt()获取实例再用remember包裹:
class UserLogic @Inject constructor( private val userRepository: UserRepository, private val analyticsHelper: AnalyticsHelper ) { // 逻辑实现 } @Composable fun MyFeatureScreen() { val userLogic = remember { hilt<UserLogic>() } // 使用逻辑类 }
二、Koin的解决方案
Koin的设计更灵活,无需依赖Android组件作为注入入口,直接支持在Composable中注入依赖,同时可轻松绑定实例与Composable生命周期:
- 先在Koin模块中声明依赖:
val appModule = module { single<UserRepository> { UserRepositoryImpl() } factory<UserLogic> { UserLogic(get()) } }
- 在Composable中用
rememberKoinInject()直接获取逻辑类实例,它会自动绑定到Composable的生命周期,退出组合时实例被回收:
@Composable fun MyFeatureScreen() { val userLogic = rememberKoinInject<UserLogic>() // 使用逻辑类处理UI逻辑 }
Koin的优势是配置轻量化,对非Android组件的注入支持更直接。
三、关于“Activity注入Repository再传递”的问题
你担心的违反关注点分离原则是对的——Activity不应该承担传递Composable依赖的职责,这种方式会拉高Activity与Composable的耦合度,降低Composable的复用性。正确的做法是让Composable自行获取所需依赖,Hilt和Koin都能实现这一点。
四、是否需要自行实现依赖注入?
完全没必要。自行实现DI不仅要维护大量模板代码,还容易出现生命周期管理、依赖作用域的问题,Hilt和Koin都是成熟的DI库,已经覆盖了这些场景,直接使用即可。
内容的提问来源于stack exchange,提问作者mohamed shawky
相关产品推荐
相关产品推荐

