使用AssistedInjection时,如何让Hilt识别ViewModel并作用域化依赖?
我正在创建一个构造函数包含非传递依赖参数的ViewModel,示例代码如下:
class MyViewModel( private val fetchUserUseCase: FetchUserUseCase, private val fetchNewsUseCase: FetchNewsUseCase, myCustomParameter: String = "", myOtherCustomParameter: Long = -1L ) : ViewModel()
由于最后两个自定义参数,我无法使用@HiltViewModel注解。当使用@AssistedInjection创建自定义ViewModel Factory时,尝试将FetchNewsUseCase作用域标记为@ViewModelScoped,会出现错误:
error: [Dagger/MissingBinding] FetchNewsUseCase cannot be provided without an @Provides-annotated method.
请问如何让Hilt/Dagger将MyViewModel识别为“Hilt ViewModel”?
要让带自定义参数的ViewModel被Hilt正确处理,需结合@AssistedInject、@Assisted及自定义Factory,同时正确配置依赖的作用域与提供方式,具体步骤如下:
1. 改造ViewModel构造函数
将自定义参数标记为@Assisted,并使用@AssistedInject替代默认构造,同时定义配套的@AssistedFactory接口:
class MyViewModel @AssistedInject constructor( private val fetchUserUseCase: FetchUserUseCase, private val fetchNewsUseCase: FetchNewsUseCase, @Assisted private val myCustomParameter: String, @Assisted private val myOtherCustomParameter: Long ) : ViewModel() { @AssistedFactory interface Factory { fun create(myCustomParameter: String, myOtherCustomParameter: Long): MyViewModel } }
2. 配置@ViewModelScoped依赖的绑定
若FetchNewsUseCase标记了@ViewModelScoped,需确保它有合法的实例提供方式:
- 构造注入方式:为
FetchNewsUseCase的构造函数添加@Inject注解,同时指定作用域:
@ViewModelScoped class FetchNewsUseCase @Inject constructor( // 此处传入该用例的依赖项 ) { // 业务逻辑实现 }
- 模块提供方式:在Hilt模块中添加
@Provides方法,指定作用域并关联ViewModelComponent:
@Module @InstallIn(ViewModelComponent::class) object UseCaseModule { @Provides @ViewModelScoped fun provideFetchNewsUseCase(): FetchNewsUseCase { return FetchNewsUseCase(/* 传入依赖参数 */) } }
注意:@ViewModelScoped的依赖必须安装在ViewModelComponent中,才能让Hilt在ViewModel作用域内提供实例。
3. 在页面中获取ViewModel实例
在Activity或Fragment中,通过Hilt注入自定义Factory,再结合viewModels()委托获取ViewModel:
class MyActivity : AppCompatActivity() { @Inject lateinit var myViewModelFactory: MyViewModel.Factory private val viewModel: MyViewModel by viewModels { myViewModelFactory.create("自定义字符串参数", 123L) } // 页面其他逻辑 }
关键注意事项
- 禁止混用
@HiltViewModel与@AssistedInject:@HiltViewModel仅适用于无自定义参数的ViewModel,带自定义参数必须使用@AssistedInject+@AssistedFactory组合。 - 确保依赖作用域与组件匹配:
@ViewModelScoped依赖的模块必须@InstallIn(ViewModelComponent::class),否则Hilt无法识别作用域。 - 所有依赖需有明确绑定:无论是构造注入还是模块提供,必须让Dagger能找到对应的实例生成逻辑,避免
MissingBinding错误。
内容的提问来源于stack exchange,提问作者Augusto Carmo

