1

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?

4
  • Did you add @HiltViewModel annotation to your viewmodel? Commented Oct 11, 2022 at 8:07
  • yes i add it to my viewmodel Commented Oct 11, 2022 at 8:27
  • please, add your viewModel code, and style your answer correct Commented Oct 11, 2022 at 8:37
  • @VeraIureva Sorry for that, I edit my question Commented Oct 11, 2022 at 8:43

2 Answers 2

1

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()
Sign up to request clarification or add additional context in comments.

4 Comments

it return this error: E/AndroidRuntime: FATAL EXCEPTION: main Process: ir.arinateam.dictionary, PID: 25218 java.lang.IllegalArgumentException: CreationExtras must have a value by SAVED_STATE_REGISTRY_OWNER_KEY` at androidx.lifecycle.SavedStateHandleSupport.createSavedStateHandle(SavedStateHandleSupport.kt:91) `
please, show your hilt and navigation dependencies
where do you try to call that code? in onCreate or as a property? You should do that as property
//Dagger - Hilt implementation 'com.google.dagger:hilt-android:2.44' kapt 'com.google.dagger:hilt-compiler:2.44' // For instrumentation tests androidTestImplementation 'com.google.dagger:hilt-android-testing:2.44' kaptAndroidTest 'com.google.dagger:hilt-compiler:2.44' // For local unit tests testImplementation 'com.google.dagger:hilt-android-testing:2.44' kaptTest 'com.google.dagger:hilt-compiler:2.44' implementation 'androidx.hilt:hilt-navigation:1.0.0' I test both in onCreate and as property.
0

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'

1 Comment

when I initialize viewmodel as property, gives me this crash log: java.lang.IllegalArgumentException: CreationExtras must have a value by SAVED_STATE_REGISTRY_OWNER_KEY

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.