Для ViewModels
, который имеет только зависимости времени компиляции, я использую компоненты ViewModelProvider.Factory
from Architecture, как показано ниже:
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
и т. д., которые доступны во время компиляции, и я могу либо 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()
})
}
ProductsAdapter
связывает ProductViewModel
с раскладкой list_item_products
.
Как я упоминал в комментариях к коду, я не хочу создавать ProductViewModel
сам, а вместо этого хочу, чтобы это было только из кинжала. Я также считаю, что правильным подходом было бы внедрить ProductsAdapter
непосредственно в Fragment
, но также мне нужно указать dagger, откуда он может получить объект Product
для ProductViewModel
, который доступен во время выполнения, и он заканчивается тем же вопросом для меня.
Любое руководство или указания для достижения этого было бы действительно здорово.