对于仅具有编译时依赖关系的ViewModels
,我使用来自架构组件的ViewModelProvider.Factory
,如下所示:
class ViewModelFactory<T : ViewModel> @Inject constructor(private val viewModel: Lazy<T>) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModel.get() as T
}
在我的Activity
或Fragment
中,我按照以下方式获取ViewModel
:
@Inject
lateinit var viewModelFactory: ViewModelFactory<ProductsViewModel>
这段代码在我的
ViewModel
需要一个仅在运行时才能使用的依赖项时就会出问题。情境是这样的,我有一个
Product
列表,我正在RecyclerView
中显示它们。对于每个Product
,我都有一个ProductViewModel
。现在,
ProductViewModel
需要各种依赖项,比如ResourceProvider
、AlertManager
等,这些依赖项在编译时就可用,我可以使用constructor
注入它们,也可以使用Module
提供它们。但是,除了上述依赖项之外,它还需要Product
对象,而这个对象只能通过API调用在运行时获取。我不知道如何注入仅在运行时才能使用的依赖项。因此,我目前正在执行以下操作:
ProductsFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
productsAdapter = ProductsAdapter(context!!, products, R.layout.list_item_products, BR.productVm)
rvProducts.layoutManager = LinearLayoutManager(context)
rvProducts.addItemDecoration(RecyclerViewMargin(context, 10, 20))
rvProducts.adapter = productsAdapter
getProducts()
}
private fun getProducts() {
productsViewModel.getProducts()
.observe(this, Observer { productResponse: GetProductResponse ->
products.clear()
productsAdapter?.notifyDataSetChanged()
val productsViewModels = productResponse.data.map { product ->
// Here product is fetched run-time and alertManager etc are
// injected into Fragment as they are available compile-time. I
// don't think this is correct approach and I want to get the
// ProductViewModel using Dagger only.
ProductViewModel(product, resourceProvider,
appUtils, alertManager)
}
products.addAll(productsViewModels)
productsAdapter?.notifyDataSetChanged()
})
}
ProductsAdapter
将 ProductViewModel
与 list_item_products
布局绑定。正如我在代码注释中提到的,我不想自己创建 ProductViewModel
,而是希望仅从dagger获取它。我认为正确的方法是直接将 ProductsAdapter
注入到 Fragment
中,但是这样做之后,我还需要告诉 dagger 在运行时从哪里获取 ProductViewModel
的 Product
对象,这对我来说仍然是一个问题。如果有任何指导或方向来实现这一点,那将非常棒。