You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:45:40