Fehru Mandala Putra
Fehru Mandala Putra

Reputation: 11

Cannot inject ViewModelFactory using Hilt

I tried to inject a value at runtime using Hilt and found that using assisted injection was the suggested approach. However, the error indicated that I should use ViewModelProvider instead. The challenge arises because in my ViewModel constructor, I need to inject the repository as well, so I cannot use the regular ViewModelProvider.

this is the error message:

public abstract static class SingletonC implements ShoppingListApplication_GeneratedInjector,
                         ^
  Injection of an assisted factory for Hilt ViewModel is prohibited since it can not be used to create a ViewModel instance correctly.
  Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead.
  Injected factory: com.example.shoppinglist.ui.detail.DetailViewModel.Factory
  
      com.example.shoppinglist.ui.detail.DetailViewModel.Factory is requested at
          com.example.shoppinglist.di.ViewModelFactoryProvider.mainViewModelFactory() [com.example.shoppinglist.ShoppingListApplication_HiltComponents.SingletonC ? com.example.shoppinglist.ShoppingListApplication_HiltComponents.ActivityRetainedC ? com.example.shoppinglist.ShoppingListApplication_HiltComponents.ViewModelC]

this is my viewmodel:

@HiltViewModel(assistedFactory = DetailViewModel.Factory::class)
class DetailViewModel @AssistedInject constructor(
    private val repository: Repository,
    @Assisted itemId: Int
) : ViewModel() {
    {...}

    @AssistedFactory
    interface Factory {
        fun create(itemId: Int): DetailViewModel
    }
}

this is my module:

@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {

    @Provides
    fun provideRepository(listDao: ShoppingListDao,itemDao: ItemDao,storeDao: StoreDao): Repository {
        return Repository(listDao,itemDao,storeDao)
    }

    @Provides
    fun provideDetailViewModelFactory(factory: DetailViewModel.Factory, itemId: Int): ViewModelProvider.Factory {
        return object: ViewModelProvider.Factory{
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return factory.create(itemId) as T
            }
        }
    }
}

@EntryPoint
@InstallIn(ViewModelComponent::class)
interface ViewModelFactoryProvider{
    fun mainViewModelFactory(): DetailViewModel.Factory
}

this is my composable function that need viewmodel:

@Composable
fun DetailScreen(
    id: Int,
    navigateUp: () -> Unit
) {
    val factory = EntryPointAccessors.fromActivity(
        LocalContext.current as Activity,
        ViewModelFactoryProvider::class.java
    ).mainViewModelFactory()
    val viewModel: DetailViewModel = viewModel(
        factory = provideDetailViewModelFactory(factory,id)
    )
}

i need to inject a value at runtime but at the sametime providing repository to my viewmodel

Upvotes: 1

Views: 307

Answers (0)

Related Questions