如何将Koin的ViewModel注入逻辑迁移到Base Fragment中?
问题原因
- 你声明的
viewModel属性类型错误,写为TypeToken<T>而非实际需要的泛型类型T,所以无法识别ViewModel的自定义方法。 - 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
相关产品推荐
相关产品推荐

