Search code examples
androidkotlinandroid-roomkotlin-coroutineskotlin-flow

How to initialize a flow in viewmodel with a suspend function as parameter


I am working with room database and datastore . Here is my code

ViewModel

@HiltViewModel
class SubscriptionViewModel @Inject constructor(
    private val userDataStore: UserDataStore,
    private val walletDao: WalletDao
) : ViewModel() {

val flow: Flow<List<Transaction>> = walletDao.getAllTransactions(userDataStore.getId()) 
 // This shows an error as userDataStore.getId() is a suspend function in DataStore


 init {
        viewModelScope.launch(IO) {
            getWalletAmount()
        }
    }
}

DataStore

 suspend fun getId(): String {
        val preferences = dataStore.data.first()
        return preferences[USER_ID] ?: ""
    }

WalletDao

 @Query("SELECT * FROM recent_transactions where user_id=:user_id")
    fun getAllTransactions(user_id: String): Flow<List<Transaction>>

The problem is I am unable to initialise the flow. I tried initialising it in the init{ } block using lateinit , but while accessing in the fragment it crashes saying flow has not been initialised.

Any solution would help.


Solution

  • You can wrap it in a flow builder.

    val flow: Flow<List<Transaction>> = flow {
        val source = walletDao.getAllTransactions(userDataStore.getId())
        emitAll(source)
    }
    

    If you want it to pre-load (start getting the first value even before anything collects the flow), then you should turn it into a SharedFlow by tacking this on:

    .shareIn(viewModelScope, SharingStarted.Eagerly, replay = 1)