I am looking for a way to chain several flows in similar way as operations were chained in RxJava. Here is a code of current implementation:
driverPreferencesFlow
.stateIn(lifecycleScope)
.transform<DriverPreferences, Response<DriverCredentials>> { it ->
Log.d(App.TAG, "Got driver from cache, ask for driver from server")
repo.getDriver(it.driver.cell, it.driver.secret)
}
.onStart {
}
.onCompletion { e ->
}
.catch { e ->
Log.e(App.TAG, "Something went wrong on loading with driver", e)
Response.Error.Exception(e)
}
.collect { it ->
Log.d(App.TAG, "Got driver from server")
Log.d(App.TAG, "Collect new driver state ${it.javaClass}")
_newDriverState.value = it
}
At this implementation, the second operation/call (repo.getDriver()
) is called, but never finished. Seems suspended.
What is your way to implement similar task?
CodePudding user response:
Am not sure why you're using transform
and not a map
or flatMap
, but according to the documentation you have to emit
the value from within the transform function, so I'd assume it'd look like:
.transform<DriverPreferences, Response<DriverCredentials>> { it ->
Log.d(App.TAG, "Got driver from cache, ask for driver from server")
emit(repo.getDriver(it.driver.cell, it.driver.secret))
}
CodePudding user response:
When you want to get emits from one Flow
and then create another one based on the elements of the first one, you need to use flatMap
operation (flatMapConcat
/flatMapMerge
), same way as in RxJava. Here is a simple examle with two flows of Integers where you can see usage of both flatMap
and map
operators:
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
val a = flowOf(1, 2, 3)
val b = flowOf(3, 4, 5)
val result = a.flatMapConcat { intFromA ->
b.map { intFromB ->
intFromA intFromB
}
}
runBlocking {
launch {
result.collect {
print(it)
}
}
}
And yes, as @romstn correctly pointed out, transform
operator requires manual calls to emit
function, similarly to Observable.create()
in RxJava: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/transform.html