How to inject Kotlin extentsion properties using Dagger-Hilt

Viewed 833

I'm trying to implement Proto Datastore using Kotlin serialization and Hilt.

Reference: https://medium.com/androiddevelopers/using-datastore-with-kotlin-serialization-6552502c5345

I couldn't inject DataStore object using the new DataStore creation syntax.

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

    @ExperimentalSerializationApi
    @Singleton
    @Provides
    fun provideDataStore(@ApplicationContext context: Context): DataStore<UserPreferences> {
        val Context.dataStore: DataStore<UserPreferences> by dataStore(
            fileName = "user_pref.pb",
            serializer = UserPreferencesSerializer
        )
        return dataStore
    }

}

I get the lint message Local extension properties are not allowed

How can inject this Kotlin extension property? Or is there any way to inject dataStore object?

2 Answers

You can't use extensions in a local context, you should call this way:

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

    @ExperimentalSerializationApi
    @Singleton
    @Provides
    fun provideDataStore(@ApplicationContext context: Context): DataStore<UserPreferences> =
         DataStoreFactory.create(
            serializer = UserPreferencesSerializer,
            produceFile = { context.dataStoreFile("user_pref.pb") },
        )
}

Found a way to do this using Predefined qualifers in Hilt

Now no DataStoreModule class. I directly inject the application context into a Datastore Manager class. Below is the code.

@Singleton
class DataStoreManager @Inject constructor(
    @ApplicationContext private val context: Context,
) {

    private val Context.userPreferencesDataStore: DataStore<UserPreferences> by dataStore(
        fileName = "user_pref.pb",
        serializer = UserPreferencesSerializer
    )

    val userPreferencesFlow: Flow<UserPreferences> =
        context.userPreferencesDataStore.data.catch { exception ->
            // dataStore.data throws an IOException when an error is encountered when reading data
            if (exception is IOException) {
                Timber.e("Error reading sort order preferences. $exception")
                emit(UserPreferences())
            } else {
                throw exception
            }
        }

    suspend fun updateUid(uid: String) {
        context.userPreferencesDataStore.updateData { userPreferences ->
            userPreferences.copy(uid = uid)
        }
    }

    suspend fun getUid(): String {
        return userPreferencesFlow.first().uid
    }
}

This works like a charm.

Related