San*_*iya 5 android dependency-injection assisted-inject dagger-2 android-viewmodel
对于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
}
Run Code Online (Sandbox Code Playgroud)
在我Activity或Fragment我得到ViewModel以下方式:
@Inject
lateinit var viewModelFactory: ViewModelFactory<ProductsViewModel>
Run Code Online (Sandbox Code Playgroud)
这工作正常,直到我ViewModel需要一个仅在运行时可用的依赖项。
场景是,我有一个列表Product,我在RecyclerView. 对于每个Product,我都有ProductViewModel。
现在,ProductViewModel需要各种依赖关系的喜欢ResourceProvider,AlertManager等这些都可以编译时,我可以Inject他们使用 constructor 或者我可以Provide他们使用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()
})
}
Run Code Online (Sandbox Code Playgroud)
ProductsAdapter将ProductViewModel与list_item_products布局绑定。
正如我在代码中的注释中提到的,我不想创建ProductViewModel我自己,而只想从 dagger 中创建它。我还认为,正确的做法是进样的ProductsAdapter直接进入Fragment,但后来也有,我需要告诉从那里可以得到匕首Product对象ProductViewModel是在运行时可用它为我结束了在同样的问题。
任何实现这一目标的指南或方向都会非常棒。
您想要注入依赖项而不是像使用ProductViewModel. 但是,是的,您不能注入 ProductViewModel,因为它需要一个仅在运行时可用的 Product。
这个问题的解决方法是创建一个ProductViewModel的Factory:
class ProductViewModel(
val product: Product,
val resourceProvider: ResourceProvider,
val appUtils: AppUtils,
val alertManager: AlertManager
) {
// ...
}
class ProductViewModelFactory @Inject constructor(
val resourceProvider: ResourceProvider,
val appUtils: AppUtils,
val alertManager: AlertManager
) {
fun create(product: Product): ProductViewModel {
return ProductViewModel(product, resourceProvider, appUtils, alertManager)
}
}
Run Code Online (Sandbox Code Playgroud)
然后注入 ProductViewModelFactory您的ProductsFragment课程,并productViewModelFactory.create(product)在产品可用时调用。
随着您的项目开始变大并且您看到这种模式重复出现,请考虑使用AssistedInject来减少样板文件。
| 归档时间: |
|
| 查看次数: |
723 次 |
| 最近记录: |