首次使用Hilt的字典App崩溃,无法创建ViewModel实例
问题:使用Hilt依赖注入时,无法创建WordInfoViewModel实例导致App崩溃
崩溃日志
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)
相关代码
WordInfoModule类
@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) } }
MainActivity代码
@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() } } } } } }
WordInfoViewModel代码
@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() } }
问题原因
你在MainActivity中手动指定SavedStateViewModelFactory创建ViewModel,绕过了Hilt的依赖注入机制。WordInfoViewModel用@HiltViewModel注解标记,且构造函数通过@Inject声明需要注入GetWordInfo实例,只有Hilt提供的ViewModelFactory才能正确解析并注入这些依赖。手动传入的SavedStateViewModelFactory无法获取Hilt管理的依赖实例,导致ViewModel创建失败引发崩溃。
另外需确认自定义Application类是否添加@HiltAndroidApp注解,这是Hilt初始化的必要条件,缺失也会导致依赖注入失败。
解决方案
修改MainActivity的ViewModel初始化代码:
移除手动指定的工厂类,直接使用默认的viewModels()委托,Hilt会自动提供适配的Factory:val viewModel: WordInfoViewModel by viewModels()确保Application类添加@HiltAndroidApp注解:
若未创建自定义Application类,新建并添加注解:@HiltAndroidApp class DictionaryApplication : Application()同时在
AndroidManifest.xml中指定该Application:<application android:name=".DictionaryApplication" ...> ... </application>
完成以上修改后,Hilt就能正确注入GetWordInfo实例,ViewModel可正常创建,App不会再崩溃。
内容的提问来源于stack exchange,提问作者Pooya Jannati Poor
相关产品推荐
相关产品推荐

