ursus
03/23/2021, 8:57 PMflowOf {
someSuspendFunction()
}
am I missing something, or is it left to clients to create such extension
comming from rx, I have it mapped in by brain as such
Observable.just == flowOf(value)
Observable.fromCallable == flowOf { .. }
vineethraj49
03/24/2021, 12:24 PMDispatchers.Default
threads (Runtime.getRuntime().availableProcessors()
) are blocked under runBlocking
, a GlobalScope.future(<http://Dispatcher.IO|Dispatcher.IO>)
also fails to launch; why is this the case?ursus
03/24/2021, 2:06 PMrunCatching
in coroutines for control flow? I gather it will catch CancelationException as well. Won't that break stuff?Brian Dilley
03/24/2021, 4:06 PMnatario1
03/25/2021, 3:55 PMPatrick Ramsey
03/26/2021, 12:39 AMBut what if the extracted function contains a coroutine builder which is invoked on the current scope? In this case, theParticularly, what does it mean that having an explicit CoroutineScope as a field on a class containing the target function is preferable to calling CoroutineScope(…)? How else would you create an explicit CoroutineScope as a field, other thanmodifier on the extracted function is not enough. Makingsuspend
an extension method ondoWorld
is one of the solutions, but it may not always be applicable as it does not make the API clearer. The idiomatic solution is to have either an explicitCoroutineScope
as a field in a class containing the target function or an implicit one when the outer class implementsCoroutineScope
. As a last resort, CoroutineScope(coroutineContext) can be used, but such an approach is structurally unsafe because you no longer have control on the scope of execution of this method. Only private APIs can use this builder.CoroutineScope
val scope = CoroutineScope(…)
?Antoine Gagnon
03/26/2021, 5:26 PMEmil Kantis
03/26/2021, 6:57 PMCOROUTINE_SUSPENDED
? I'm building an AOP-based logging interceptor and need to check if the return value of a reflective methodcall is COROUTINE_SUSPENDED
🙂 Currently doing this by checking if (result.toString() == "COROUTINE_SUSPENDED")
but it feels like I should be able to access the symbol directly..zak.taccardi
03/27/2021, 6:48 PMcallbackFlow
vs channelFlow
. It seems the latter respects operator fusion, but the prior does not?ursus
03/28/2021, 2:14 PMByron Katz
03/28/2021, 9:19 PM- executorService: ExecutorService = Executors.newCachedThreadPool(Executors.defaultThreadFactory())
+ executorService: ExecutorService = Executors.newCachedThreadPool(Executors.defaultThreadFactory()).asCoroutineDispatcher().executor as ExecutorService,
and bam! Performance up by 40% on my heaviest function.Lilly
03/28/2021, 9:28 PMcoroutineScope
and within this scope I want to cancel it. How can I prevent cancel cooperation of this scope, so that cancellation isn't propagated?svenjacobs
03/29/2021, 6:32 AMsuspend fun showSnackbar() {
val snackbar = Snackbar.make(...)
snackbar.show()
delay(4000)
snackbar.setAction("...", null) // crash here
snackbar.dismiss()
}
The functions is called via launch(Dispatchers.Main) { showSnackbar() }
. Please don't ask why I have to null
the action. It is required to prevent a false positive memory leak warning. Anyway, the call snackbar.setAction()
crashes the app with android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
and I wonder if delay()
might change the Dispatcher?? 🤔 Thanks for your help!Lilly
03/29/2021, 8:58 AMcoroutineScope {
launch {
if (condition) cancel() // does not cancel the coroutine of flow
}
launch {
dataSource.channel.receiveAsFlow() {
.collect { doSomething() }
}
}
I would expect that cancelling first coroutine would cancel second coroutine but it doesn't. Any ideas?Lukasz Kalnik
03/29/2021, 3:29 PMSharedFlow
that cancels the flow automatically after all subscribers have left? Something like refCount()
in RxJava.Lilly
03/29/2021, 3:51 PMChannel
without removing the element?ursus
03/29/2021, 9:50 PMfun intervalFlow(delayMillis: Long): Flow<Int> {
return flow {
withContext(Dispatchers.Default) {
var i = 0
emit(i)
while (true) {
delay(delayMillis)
emit(++i)
}
}
}
}
wrong -- I mean I read the article, but at runtime it doesnt crash, and printing threads in each step, seems correctdewildte
03/29/2021, 11:15 PMViewModel
collect from a Flow<T>
given to it by a View
, Activity
or Fragment
?
I.E.
// MyView.kt
val events: Flow<Event> = flowOf(Event1, Event2)
viewModel.handleEvents(events)
ursus
03/30/2021, 2:35 AM@Test fun `doSomething should move state to FINAL`() {
val viewModel = createViewModel(initialState = State.INITIAL)
val testSubscriber = viewModel.state.test()
viewModel.doSomething()
testSubscriber.assertValues(State.INITIAL, State.FINAL)
}
TheMrCodes
03/30/2021, 10:12 AMMutableStateFlow
Susheel
03/30/2021, 6:15 PMOleg Siboglov
03/30/2021, 11:19 PMsuspend fun foo(): Bar {
// I call another suspend function here returning an intermediate value.
if (error) {
suspendCancellableCoroutine<Bar> { continuation ->
val listener = object : Listener {
override fun callback() {
// I need to call this suspend function again.
// However, here is where I get an error.
continuation.resume(foo())
}
}
// I call other functions that will eventually call the listener.
}
}
}
The error that I get is obvious - Suspension functions can be called only within coroutine body
. However, I’m not really quite sure on how to resume the coroutine properly. Any help is much appreciated. Thank you.dan.the.man
03/31/2021, 4:38 PMNoel Stieglitz
03/31/2021, 7:28 PMsuspend fun fetchTwoThings(): TheResultsModel =
coroutineScope {
val job1 = getStuff1(this) // both of these functions use the passed in coroutine scope like scope.async(<http://Dispatchers.IO|Dispatchers.IO>) { ... API call here }
val job2 = getStuff2(this)
awaitAll(job1, job2)
return@coroutineScope TheResultsModel(
thing1 = job1.await(),
thing2 = job2.await()
}
Is there any downside to using the coroutineScope
like this in the repository? Alternatively, I could pass in the viewModelScope
. Maybe that's ok since the ViewModel class instantiates the repo as a member variable. The lifetime of the repository is already tied to the ViewModel class. Yet another option is to expose getStuff1
and getStuff2
to the ViewModel, and manage the coroutine there. I'm not a huge fan of that since I might want to call fetchTwoOtherThings
from other places and would have to duplicate that code. What are your thoughts? How can I do this better?ursus
03/31/2021, 8:47 PMDispatchers.Unconfined
equal to rx Schedulers.trampoline()
?
if so, why does my code not run blockingly if I replace all dispatcher references with the Unconfined
one? That's what I used to do for testing in rx
Is it not supposed to? To not impose any threading, i.e. run on native unit test thread?
(Im aware of TestDispatcher, that works as expected)alex.tavella
03/31/2021, 9:10 PMThis job has not completed yet
on the following test:
@Test
fun requestWithTimeout_serverRespondsInTime_returnsResponse() = coroutinesRule.testDispatcher.runBlockingTest {
val body = "{ field: Test }"
val response = MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(body)
.throttleBody(body.length.toLong() / 2, 9, TimeUnit.SECONDS)
mockWebServer.enqueue(response)
val actual = service.requestWithTimeout(20_000)
assertEquals(ResponseTest("Test"), actual)
}
Shawn Witte
03/31/2021, 9:25 PMsuspend
function via Retrofit) that is part of my (Android app's ) data syncing. I am attempting to ensure that the code block with this call completes, even if the calling coroutine (started in a viewModelScope
) is cancelled. My initial thought was to wrap the function in appScope.async { //code }.await()
, where appScope
is an application-level scope. Android Studio has suggested that I just use withContext(appScope.coroutineContext) { //code }
.
Are these really equivalent in terms of coroutine lifecycles? I had thought that withContext
created a child coroutine (with a different, but related CoroutineContext
) that would be cancelled if the context creating it is cancelled, whereas appScope.async()
creates a whole new coroutine with its own lifecycle tied to appScope
and not the original context.
Also welcoming input on my solution to the initial problem.Dmytro Serdiuk
04/01/2021, 4:10 PMfun main() = runBlocking<Unit> {
val counter = counterActor() // create the actor withContext(Dispatchers.Default) {
massiveRun {
counter.send(IncCounter)
}
}
// send a message to get a counter value from an actor
val response = CompletableDeferred<Int>()
counter.send(GetCounter(response))
println("Counter = ${response.await()}")
counter.close() // shutdown the actor
}
Actor is more efficient than locking under load, because in this case it always has work to do and it does not have to switch to a different context at all.
How to understand it?And how is it efficient than locks?dan.the.man
04/01/2021, 4:54 PMemit(newValue)
and value = newValue
like there was for post/value in Livedata? I'm not seeing any documentation, I think we're supposed to use Emit, but using value = appears to be working in my code?Robert Jaros
04/01/2021, 10:48 PMRobert Jaros
04/01/2021, 10:48 PMephemient
04/01/2021, 11:15 PM.onEach {}
would be "before" subscribers get each value, although the resulting type isn't StateFlow anymore so not sure if that would work for youDominaezzz
04/02/2021, 5:53 AM