Jetpack DataStore依赖注入报错:splashViewModel未初始化
核心问题
你遇到的kotlin.UninitializedPropertyAccessException确实和Hilt依赖注入未正确配置有关:MainModule未被Hilt自动扫描识别、Activity未开启Hilt注入能力是主要原因,导致@Inject标注的splashViewModel从未被初始化就被调用。
分步解决
1. 配置Hilt应用入口
Hilt需要通过自定义Application类初始化依赖容器,必须给Application类添加@HiltAndroidApp注解:
@HiltAndroidApp class MyApp : Application() {}
然后在AndroidManifest.xml中指定该Application:
<application android:name=".MyApp" <!-- 其他原有配置 --> > <!-- 活动配置 --> </application>
2. 给MainActivity开启Hilt注入能力
在MainActivity上添加@AndroidEntryPoint注解,Hilt才能在该Activity中完成依赖注入:
@AndroidEntryPoint class MainActivity : ComponentActivity() { @Inject lateinit var splashViewModel: SplashViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) installSplashScreen().setKeepOnScreenCondition { !splashViewModel.isLoading.value } setContent{ BottomNavWithBadgesTheme { val screen by splashViewModel.startDestination // 剩余界面代码 } } } }
注意:必须先调用
super.onCreate(savedInstanceState),Hilt的注入操作是在super.onCreate过程中完成的,提前访问splashViewModel会触发未初始化异常。
3. 修正SplashViewModel的协程逻辑
原代码中collect会持续监听DataStore的Flow,导致协程被永久阻塞,_isLoading.value = false永远不会执行,闪屏会一直显示。改用first()获取一次初始状态即可结束监听:
class SplashViewModel @Inject constructor( private val repository: DataStoreRepository ) : ViewModel() { private val _isLoading: MutableState<Boolean> = mutableStateOf(true) val isLoading: State<Boolean> = _isLoading private val _startDestination: MutableState<String> = mutableStateOf(Screen.OnboardingFirstScreen.route) val startDestination: State<String> = _startDestination init { viewModelScope.launch { val completed = repository.readOnBoardingState().first() _startDestination.value = if (completed) Screen.MainScreen.route else Screen.OnboardingFirstScreen.route _isLoading.value = false } } }
关于MainModule的说明
你的MainModule标注了@InstallIn(SingletonComponent::class),只要配置了@HiltAndroidApp,Hilt会自动扫描并使用这个Module,不需要手动调用,所以“从未被使用”是正常现象,Hilt会在后台处理依赖提供逻辑。
内容的提问来源于stack exchange,提问作者Harvey Xie

