octylFractal
11/10/2020, 5:13 AMdephinera
11/10/2020, 7:48 AMdeferred.getCompleted()
, but getCompleted()
is experimental.
viewModelScope.launch(Dispatchers.MAIN) {
val deferred1 = async { operation1() }
val deferred2 = async { operation2() }
val deferred3 = async { operation3() }
val deferred4 = async { operation4() }
val results = awaitAll(deferred1, deferred2, deferred3, deferred4)
val res1 = results[0] as? Type1
val res2 = results[1] as? Type2
val res3 = results[2] as? Type3
val res4 = results[3] as? Type4
}
Larten
11/10/2020, 9:18 AMspand
11/10/2020, 10:15 AMFlorian
11/10/2020, 6:04 PMrkeazor
11/10/2020, 9:29 PMTim Malseed
11/11/2020, 6:41 AMJobCancellationException
. My crash reporting tool isn't offering any useful information, and I don't quite understand this exception..Mark McCormick
11/11/2020, 9:51 AMwitchContext(<http://Dispatchers.IO|Dispatchers.IO>)
for all the rest api calls. Do you have any suggestions? Thank you :)bobby
11/11/2020, 10:17 AMfun main() {
viewModelScope.launch {
doA()
//call api with Flow as the return type
}
}
suspend fun doA() {
viewModelScope.async { doB() }.await()
}
suspend fun doB() {
//Do logic here, eventually will call line below
viewModelScope.launch { doC() }
}
suspend fun doC() {
//call api with Flow as the return type
}
What I want to achieve from the code above is to wait for the doA()
function to finished and then continue to call the API, but when I tried to run the code, the doA()
is executed first but it continue to call the API rather than waiting for the doA()
to finish. Is there's something wrong with the code? Yes, the code is quite bad, I still kind a new with the Coroutine, thanks for helping, really appreciate itariedov
11/11/2020, 12:42 PMdelay
inside each call inside the scope.launch
.
Any suggestions would be very welcome, thank you!Evgeniy Zaharov
11/11/2020, 2:06 PMval flow = flow<Unit> {
println("Reactor context in Flow: " + coroutineContext[ReactorContext])
}
flow.asFlux()
.subscriberContext { ctx -> ctx.put("answer", 42) }
.subscribe() // Must print "Reactor context in Flow: Context{'answer'=42}" but print "Reactor context in Flow: null"
But with coroutine 1.4.0, 1.4.1 it prints Null. Am I miss something?Bruno Ortiz
11/11/2020, 7:08 PMfun main() = runBlocking<Unit> {
emit()
.onEach {
if (it == 5) error("oof! some random error occurred.")
println(it)
}.catch { println("some error occurred") }
.collect()
}
fun emit() = flow {
for (i in 1..10) {
emit(i)
}
}
This will print "1 2 3 4" and stop. I'd like to print every number except number 5. (I'm doing this to simulate a random error, i know that in this specific case i could filter out the number 5).napperley
11/11/2020, 11:46 PMTolriq
11/12/2020, 9:08 AMfun scheduleRefresh() {
job?.cancel()
job = launch {
while (isActive) {
val newRefreshTime = getARefreshTime()
if (newRefreshTime == 0) {
break
}
delay(newRefreshTime)
doSomething()
}
}
}
Nikky
11/12/2020, 4:25 PMprivate val exceptionHandler = CoroutineExceptionHandler { context, e -> GlobalScope.launch(MDCContext() + context) {
can i somehow do context.getCopyOfContextMap()
?rkeazor
11/13/2020, 5:10 AMMichal Klimczak
11/13/2020, 7:26 AM@Test
fun `stateIn self-contained example`() = runBlockingTest {
suspend fun makeHeavyRequest(): String {
return "heavy result"
}
val flow = flow<Unit> {} //in production this is a channel meant to refresh the Flow
.onStart { emit(Unit) }
.map { makeHeavyRequest() } //using mapLatest breaks
.flowOn(testDispatcher)
// .onEach { } //uncommenting this line also breaks
.stateIn(GlobalScope, SharingStarted.WhileSubscribed(), "init state")
val results = mutableListOf<String>()
val job = launch {
flow.collect { results.add(it) }
}
assertEquals("heavy result", results[0])
job.cancel()
}
1. Why the test breaks (I get init state
instead of heavy result
) when I use mapLatest
instead of map
?
2. Why the test breaks (I get init state
instead of heavy result
) when I uncomment the onEach
below the flowOn
?
3. Bonus question: why don't I get both, the init state
AND the heavy result
?FunkyMuse
11/13/2020, 10:39 AMNikky
11/13/2020, 12:03 PMsuspend fun doStuff() = withContext(MDCContext() + exceptionHandler()) {
MDC.put("flow", "do-stuff")
<http://logger.info|logger.info> { "doing stuff" } // mdc is fine here
someSuspendFun()
<http://logger.info|logger.info> { "done doing stuff" } // mdc was reset to the state of MDCContext ie. is empty
}
ideally what i would like to be able to do is update the MDCContext or update the val contextMap: MDCContextMap
after i modify the MDC
( i tried, it fails in different ways )
or use a mechanism where the MDC is stored before doing a suspend call, so any changes are actually picked up
TL;DR currently it leads to rather unnatural looking code and additional nesting or errors that are really hard to findubu
11/14/2020, 11:58 AMFlow<T>
with debounce(...)
operator applied to it has currently a pending value that will be emitted after debounce delay?
I have a specific problem with the following use case on Android. Inside a ViewModel
, I am using a Channel<String>
to organize pipeline for sending text changes to some remote backend: this channel is consumed as Flow<String>
, where on each emission the value is sent (with delay resulting from debounce()
operator) to the backend. When this ViewModel
is to be destroyed and onCleared()
is called, I cancel that same Channel<String>
. But there is an expected but still unpleasant side-effect, which I need to eliminate: the last value is not guaranteed to be sent if there is a pending emission due to debounce delay, which gets cancelled when channel.cancel()
is called.
Any suggestions will be very appreciated!Ananiya
11/14/2020, 4:42 PMArchie
11/14/2020, 6:45 PM2sec 2sec 2sec
------[A]------[B]------[C]------...----------------> InitailFlow
\ | |
\ drop drop
\
5sec \ 5sec 5sec
----------[1]---------[2]---------[3]-----|> AnotherFlow
result: [A1, A2, A3]
So I have InitailFlow
which emits a short amount of time (2 seconds) which is then transformed to AnotherFlow
which takes longer to finish (15 seconds in total)... I would like to drop the other incoming items emitted by the InitialFlow
while AnotherFlow
isn't finished...
I've tried:
flow{
delay(2000)
emit("A")
delay(2000)
emit("B")
delay(2000)
emit("C")
}.buffer(0, BufferOverflow.DROP_LATEST)
.onEach {
println("Event for $it")
}
.flatMapConcat {
flow {
delay(5000)
emit("${it}1")
delay(5000)
emit("${it}2")
delay(5000)
emit("${it}3")
}
}
.onEach {
println(it)
}
.launchIn(scope)
But for some reason this is the result:
Event for A
A1
A2
A3
Event for B
B1
B2
B3
It still process Event B for some reason even when I have a
.buffer(0, BufferOverflow.DROP_LATEST)
.
Why does it still process Event B?
Is there a way to do this? Thanks in advance.Florian
11/15/2020, 9:32 AMrunBlockingTest
, will it execute coroutines launched within it sequentially? (as if I called join
on them)Simon Lin
11/16/2020, 5:42 AMval onSuccess = SingleLiveEvent<Unit>()
fun load() {
// do something
onSuccess.call()
}
diesieben07
11/16/2020, 10:58 AMflow
?
For example if I open an IO Stream in the flow {}
builder, how do I clean it up? I can't use onCompletion
, because I don't have the stream available there obviously. If I understand the docs correctly I am not supposed to use try-finally
in the flow {}
builder, correct?Egor Egorov
11/17/2020, 5:21 AMViewModel
and last point is MockWebServer
from OkHTTP using Coroutines
. In ViewModel I make a call using viewModelScope.launch
. However when I try to run this code
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
@Test
fun reloadExpense() = runBlocking {
viewModel.reloadExpense()
assertThat(viewModel.state.value, CoreMatchers.instanceOf(LCE.Content::class.java))
}
It does not wait for API request and just finishes the test. The MainCoroutine Rule is
@ExperimentalCoroutinesApi
class MainCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(this.coroutineContext[ContinuationInterceptor] as CoroutineDispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
Dispatchers.resetMain()
}
}
I have tried using runBlockingTest
,runBlocking
and different types of rules. Nothing seems to work. Thank you in advance!John O'Reilly
11/17/2020, 11:03 AM1.4.1-native-mt
version of Kotlinx Coroutines available?Andrea Giuliano
11/17/2020, 11:59 AMMetricEmitter
where consumers can simply call emitMetric(observation)
. Under the hood this MetricEmitter
will spin up an actor responsible for ingesting those metric observations. From the external consumer of this MetricEmitter
I just want to expose methods such as:
• `metricEmitter.initialize()`: which will spin up the actor and ticker
• `metricEmitter.emitMetric()`: which will ingest the observation
• `metricEmitter.close()`: which will flush remaining metrics and tear down the actor
My problem is that in the initialize()
function, when I try creating the actor, it requires me to provide a CoroutineScope
. If I use coroutineScope { actor<Msg>{... }
this code block will freeze the whole execution since it will complete when the actor terminates. That’s not what I want. I’ve managed to solve the issue by passing a coroutineScope as argument of metricEmitter.initialize(scope: CoroutineScope)
but not sure if this is a smell/antipattern. Any idea how to solve/remodel the solution?Evgeniy Zaharov
11/17/2020, 12:47 PMTolriq
11/17/2020, 1:14 PMasSharedFlow()
on a MutableSharedFlow
vs just exposing the MutableSharedFlow
as a SharedFlow
?Tolriq
11/17/2020, 1:14 PMasSharedFlow()
on a MutableSharedFlow
vs just exposing the MutableSharedFlow
as a SharedFlow
?wasyl
11/17/2020, 1:25 PMMutableSharedFlow
as SharedFlow
then someone could still cast it back to Mutable..
and send values to it. asSharedFlow
fully hides the underlying mutable shared flow from consumersTolriq
11/17/2020, 1:31 PMwasyl
11/17/2020, 1:35 PMasSharedFlow
is imo good practice. Even if you don’t develop a library, it’s still good to make it impossible to make a mistake by fellow devs — I can imagine someone doing if (someFlow is MutableSharedFlow) someFlow.castAndSend(x)
with good intentions