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

如何将Koin的ViewModel注入逻辑迁移到Base Fragment中?

问题原因

  1. 你声明的viewModel属性类型错误,写为TypeToken<T>而非实际需要的泛型类型T,所以无法识别ViewModel的自定义方法。
  2. Koin的by inject()默认依赖实化泛型获取目标注入类型,BaseFragment中的泛型T会被类型擦除,直接在父类调用by inject()无法匹配到子类传入的具体ViewModel类型。

修正方案

方案1:父类接收ViewModel Class完成注入

只需在BaseFragment构造中增加ViewModel的Class参数,调用Koin注入时传入该参数即可,子类只需额外传递对应ViewModel的Class:

import androidx.lifecycle.ViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel

abstract class BaseFragment<T : ViewModel>(
    @LayoutRes private val layoutId: Int,
    private val vmClass: Class<T>
) : Fragment() {
    // 传入Class参数完成注入,也可使用by inject(clazz = vmClass)实现
    val viewModel: T by viewModel { parametersOf(vmClass) }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = inflater.inflate(layoutId, container, false)
}

子类使用示例:

class Fragment1 : BaseFragment<Fragment1ViewModel>(R.layout.fragment1, Fragment1ViewModel::class.java) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.testVM1() // 可正常调用
    }
}

class Fragment2 : BaseFragment<Fragment2ViewModel>(R.layout.fragment2, Fragment2ViewModel::class.java) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.testVM2() // 可正常调用
    }
}

方案2:父类声明抽象属性,子类实现注入

如果不想额外传递Class参数,可以把viewModel声明为抽象属性,由子类自己完成注入,父类仅做规范约束:

abstract class BaseFragment<T : ViewModel>(@LayoutRes private val layoutId: Int) : Fragment() {
    abstract val viewModel: T

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = inflater.inflate(layoutId, container, false)
}

子类使用示例:

class Fragment1 : BaseFragment<Fragment1ViewModel>(R.layout.fragment1) {
    override val viewModel: Fragment1ViewModel by inject()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.testVM1()
    }
}

class Fragment2 : BaseFragment<Fragment2ViewModel>(R.layout.fragment2) {
    override val viewModel: Fragment2ViewModel by inject()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.testVM2()
    }
}

内容的提问来源于stack exchange,提问作者Tomas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:18:03