简体   繁体   中英

how to return an object in a suspended function after receiving the object from a Flow?

I'm wondering if there's a way to wait for a flow to be complete and return the result inside a suspend function. transactionRepository.getAll(accountId) returns a flow of transactions

override suspend fun getAccount(accountId: Int): Account {
    val account = Account(accountRepository.get(accountId))
    transactionRepository.getAll(accountId).mapIterable {
        val transaction = Transaction(it)
        val category = Category(categoryRepository.get(it.categoryId))
        transaction.category = category
        transaction.account = account
        return@mapIterable transaction
    }.collect {
        account.transactions = it
     }

    //TODO: How can i return an account after the flow has been executed?
}

getAll function defined in my repository:

fun getAll(accountId: Int): Flow<List<DatabaseTransaction>>

Assuming you want just the first value returned by the flow, and it's a List<Transaction> , you can use first() . But I'm only guessing because I don't know what getAll() returns and I'm not familiar with mapIterable .

override suspend fun getAccount(accountId: Int): Account {
    val account = Account(accountRepository.get(accountId))
    val transactionsFlow: Flow<List<Transaction>> = transactionRepository.getAll(accountId).mapIterable {
        val transaction = Transaction(it)
        val category = Category(categoryRepository.get(it.categoryId))
        transaction.category = category
        transaction.account = account
        return@mapIterable transaction
    }
    account.transactions = transactionsFlow.first()
    return account
}

You could do two things

First one would be to use the .toList() on the flow which I think gives you the list you want then you can just do a normal for loop on that list to set the data

val transactions = transactionRepository.getAll(accountId).toList()

transactions.forEach{
    val transaction = Transaction(it)
    val category = Category(categoryRepository.get(it.categoryId))
    transaction.category = category
    transaction.account = account
}

account.transactions = transactions 

Second would be to just return the account after the collect like you normally would.

val account = Account(accountRepository.get(accountId))
transactionRepository.getAll(accountId).mapIterable {
    val transaction = Transaction(it)
    val category = Category(categoryRepository.get(it.categoryId))
    transaction.category = category
    transaction.account = account
    return@mapIterable transaction
}.collect {
    account.transactions = it
 }

return account

See this example I made

https://pl.kotl.in/wWmLiqBtz

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM