1

I followed this tutorial link

But I met a problem that "kotlin.UninitializedPropertyAccessException: lateinit property splashViewModel has not been initialized" Here is my code

@Module
@InstallIn(SingletonComponent::class)
object MainModule {

    @Provides
    @Singleton
    fun provideDataStoreRepository(
        @ApplicationContext context: Context
    ) = DataStoreRepository(context = context)
}
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "on_boarding_pref")

class DataStoreRepository(context: Context) {

    private object PreferencesKey {
        val onBoardingKey = booleanPreferencesKey(name = "on_boarding_completed")
    }

    private val dataStore = context.dataStore

    suspend fun saveOnBoardingState(completed: Boolean) {
        dataStore.edit { preferences ->
            preferences[PreferencesKey.onBoardingKey] = completed
        }
    }

    fun readOnBoardingState(): Flow<Boolean> {
        return dataStore.data
            .catch { exception ->
                if (exception is IOException) {
                    emit(emptyPreferences())
                } else {
                    throw exception
                }
            }
            .map { preferences ->
                val onBoardingState = preferences[PreferencesKey.onBoardingKey] ?: false
                onBoardingState
            }
    }
}
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 {
            repository.readOnBoardingState().collect { completed ->
                if (completed) {
                    _startDestination.value = Screen.MainScreen.route
                } else {
                    _startDestination.value = Screen.OnboardingFirstScreen.route
                }
            }
            _isLoading.value = false
        }
    }

}

And in my main activity

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
                ....
            }
        }

It turned out MainModule object have never been used. Is that problem? I'm new to jetpack data store, I just followed it, so I don't know where is the problem and how to fix it. Thank you in advance.

Harvey Xie
  • 81
  • 4

1 Answers1

0

Firstly, it's not about data store. It is about dependency injection. You are trying to get the data from viewmodel when it is not initialized. To solve the problem:

  1. Mark your viewmodel class with @HiltViewModel annotation

  2. Remove lateinit var keyword and @Inject annotation from viewmodel in your MainActivity

  3. Your viewmodel must be initialized in onCreate function like that:

    viewModel: SplashViewModel = hiltViewModel()
    
Injent
  • 479
  • 11