Home > Enterprise >  Cannot create an instance of class viewmodel hilt
Cannot create an instance of class viewmodel hilt

Time:10-11

I use hilt for the first in my dictionary app, but when I run my app, it crash and show this log:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ir.arinateam.dictionary, PID: 23787
    java.lang.RuntimeException: Cannot create an instance of class ir.arinateam.dictionary.feature_dictionary.presentation.WordInfoViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:175)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:138)

this is my module class: `@Module @InstallIn(SingletonComponent::class) object WordInfoModule {

@Provides
@Singleton
fun provideGetWordInfoUseCase(repository: WordInfoRepository): GetWordInfo {
    return GetWordInfo(repository)
}

@Provides
@Singleton
fun provideWordInfoDatabase(app: Application): WordInfoDatabase {
    return Room.databaseBuilder(
        app.applicationContext, WordInfoDatabase::class.java, "word_db"
    ).addTypeConverter(Converters(GsonParser(Gson())))
        .build()
}

@Provides
@Singleton
fun provideWordInfoRepository(
    db: WordInfoDatabase,
    api: DictionaryApi
): WordInfoRepository {
    return WordInfoRepositoryImpl(api, db.dao)
}

@Provides
@Singleton
fun provideDictionaryApi(): DictionaryApi {
    return Retrofit.Builder()
        .baseUrl(DictionaryApi.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(DictionaryApi::class.java)
}



}`

And this is my mainActivity class that init viewmodel and try to use it:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

private lateinit var bindingActivity: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    bindingActivity = DataBindingUtil.setContentView(this, R.layout.activity_main)

    val viewModel: WordInfoViewModel by viewModels {
        SavedStateViewModelFactory(application, this)
    }
    
    lifecycleScope.launch {

        viewModel.eventFlow.collectLatest { event ->

            when (event) {

                is WordInfoViewModel.UIEvent.ShowSnackbar -> {
                    Snackbar.make(bindingActivity.root, event.message, Snackbar.LENGTH_SHORT)
                        .show()
                }

            }

        }

    }
}
}

And this is my ViewModel:

@HiltViewModel
class WordInfoViewModel @Inject constructor(
private val getWordInfo: GetWordInfo
) : ViewModel() {

private val _searchQuery = mutableStateOf<String>("")
val searchQuery: State<String> = _searchQuery

private val _state = mutableStateOf<WordInfoState>(WordInfoState())
val state: State<WordInfoState> = _state

private val _eventFlow = MutableSharedFlow<UIEvent>()
val eventFlow = _eventFlow.asSharedFlow()

private var searchJob: Job? = null

fun onSearch(query: String) {

    _searchQuery.value = query
    searchJob?.cancel()
    searchJob = viewModelScope.launch {
        delay(500L)
        getWordInfo(query)
            .onEach { result ->
                when (result) {
                    is Resource.Success -> {
                        _state.value = state.value.copy(
                            wordInfoItems = result.data ?: emptyList(),
                            isLoading = false
                        )
                    }
                    is Resource.Error -> {
                        _state.value = state.value.copy(
                            wordInfoItems = result.data ?: emptyList(),
                            isLoading = false
                        )
                        _eventFlow.emit(UIEvent.ShowSnackbar(result.message ?: "Unknown Error"))
                    }
                    is Resource.Loading -> {
                        _state.value = state.value.copy(
                            wordInfoItems = result.data ?: emptyList(),
                            isLoading = true
                        )
                    }
                }
            }.launchIn(this)
    }

}

sealed class UIEvent {
    data class ShowSnackbar(val message: String) : UIEvent()
}

}

where is the problem and how can i solve it?

CodePudding user response:

In your activity, you can now just use KTX viewModels() directly.

 val viewModel: WordInfoViewModel by viewModels {
        SavedStateViewModelFactory(application, this)
    }

replace that part to

private val viewModel: MyViewModel by viewModels()

CodePudding user response:

Hilt lets you to inject SavedStateHandle into viewmodels, you could use it as:

@HiltViewModel
class WordInfoViewModel @Inject constructor(
    private val savedStateHandle: SavedStateHandle,
    private val getWordInfo: GetWordInfo
) : ViewModel() {
    ...
}

And in your activity:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: WordInfoViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) { ... }
}

If you feel comfortable with the still alpha library:

implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
  • Related