Dagger 2.16中如何将Fragment参数注入ViewModel的init块
Dagger 2.16 下 Fragment 参数注入 ViewModel 解决方案
核心思路
通过扩展SubComponent的Builder传递Fragment参数,结合自定义参数Module让Dagger能够为ViewModel提供所需的Long/String参数,最终实现ViewModel在init块中使用这些参数完成初始化。
步骤1:修改SubComponent及Builder
更新MyFragmentSubcomponent,让其Builder支持传入Fragment的参数,并将参数Module纳入SubComponent的依赖中:
@Scope annotation class MyFragmentScope @MyFragmentScope @Subcomponent(modules = [MyFragmentModule::class, MyFragmentParamsModule::class]) interface MyFragmentSubcomponent : Injector<MyFragment> { @Subcomponent.Builder interface Builder : Injector.Factory<MyFragment> { // 添加参数设置方法,用于从Fragment传递参数 fun itemId(id: Long): Builder fun itemName(name: String): Builder } }
步骤2:创建参数提供Module
新建MyFragmentParamsModule,负责将传递进来的参数提供给Dagger容器:
@Module class MyFragmentParamsModule( private val itemId: Long, private val itemName: String ) { @Provides @MyFragmentScope fun provideItemId(): Long = itemId @Provides @MyFragmentScope fun provideItemName(): String = itemName }
步骤3:适配ViewModel构造函数
让MyFragmentViewModel的构造函数通过@Inject接收参数,同时保留原有常规依赖:
class MyFragmentViewModel @Inject constructor( private val itemId: Long, private val itemName: String, // 其他常规依赖,比如Repository等 private val myRepository: MyRepository ) : ViewModel() { init { // 在这里直接使用itemId和itemName完成初始化逻辑 initData(itemId, itemName) } private fun initData(id: Long, name: String) { // 初始化实现 } }
步骤4:在Fragment中构建SubComponent并注入
在Fragment中从arguments取出参数,通过Builder传入并构建SubComponent,完成注入:
class MyFragment : Fragment() { private lateinit var viewModel: MyFragmentViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 从arguments获取参数 val itemId = arguments?.getLong("ITEM_ID") ?: 0L val itemName = arguments?.getString("ITEM_NAME") ?: "" // 构建SubComponent并注入Fragment val subcomponent = DaggerMyFragmentSubcomponent.builder() .itemId(itemId) .itemName(itemName) .create(this) subcomponent.inject(this) // 通过ViewModelProvider获取ViewModel(Dagger已绑定到Map中) viewModel = ViewModelProvider(this)[MyFragmentViewModel::class.java] } }
关键说明
- 自定义ViewModelFactory无效的原因:Dagger的
@Binds @IntoMap机制会覆盖自定义Factory的创建逻辑,必须让Dagger容器能够直接获取带参数的ViewModel实例,因此通过SubComponent传递参数是唯一可行的方式。 - 保持
MyFragmentModule的原有逻辑不变,它负责将ViewModel绑定到Dagger的ViewModel Map中,确保ViewModelProvider能正确获取实例。
内容的提问来源于stack exchange,提问作者Mlirog
相关产品推荐
相关产品推荐

