voben
12/05/2019, 11:09 PMIllegalStateException: This job has not completed yet
. I have a channel in my viewmodel which I expose as a flow
ViewModel
private val _channel = BroadcastChannel<Boolean>(1)
val myFlow = _channel.asFlow()
fun sendToChannel() {
viewModelScope.launch {
_channel.send(true)
}
}
And in my activity, I collect the flow
lifecycleScope.launch {
myFlow.collect { println(it) }
}
My Test
@Test
fun `myTest`() = runBlockingTest {
viewModel.myFlow.collect { myVal ->
assertTrue(myVal)
}
viewModel.sendToChannel()
}
How do I ensure the assertion is called. Or what’s a better way of testing this?ursus
12/06/2019, 4:37 AMjk2018
12/06/2019, 5:45 PMAnimesh Sahu
12/08/2019, 11:02 AMCoroutineScope(context).async{}.await()
or withContext(context) {}
?Animesh Sahu
12/08/2019, 11:11 AMDispatchers.Default+<http://Dispatchers.IO|Dispatchers.IO>
? (I know its not intended i'm just curious of the functionality)asad.awadia
12/08/2019, 3:49 PMColton Idle
12/09/2019, 8:00 AMfun buttonClick() {
viewModelScope.launch {
delay(10000)
_myPrivateData.value = "Two"
}
}
Is there an easy way to tell when a suspend function will run on a different thread? For example, I will be using coroutines with Retrofit and at first it seems like I would have to tell it to run on a different thread, but it seems like I won't have to do that from the tutorials I've read?Dmitry Khasanov
12/09/2019, 11:51 AMnerdstone
12/09/2019, 2:25 PMGabriel Feo
12/09/2019, 6:38 PMDeferred
and awaitAll
, but I don't know how I should do this with simple `Job`sjimn
12/09/2019, 9:35 PMDaniel Asher
12/10/2019, 5:37 AMSupervisorJob
and to launch
a new coroutine for every transition so as not to have parent coroutines cancelled, but when I’m calling the API, I can’t quite figure out how to get the exception back to the client. Here’s some code, apologies for any conceptual errors on my part:
class CoroutineExceptionTest: BehaviorSpec() {
val supervisorJob = SupervisorJob()
val coroutineScope: CoroutineScope = CoroutineScope(newSingleThreadContext("serviceContext") + supervisorJob)
class InvalidEventException(override val message: String): Exception(message)
fun tryTransition(state: Int, event: Int): Int {
return when (event >= state) {
true -> event + state
false -> throw InvalidEventException("Argument $event is invalid")
}
}
val stateChannel = ConflatedBroadcastChannel(0)
val currentState: Int get() = stateChannel.value
var eventChannel = coroutineScope.actor<Int>() {
for (event in channel) {
if (coroutineScope.isActive) {
launch {
val newState = tryTransition(currentState, event)
stateChannel.send(newState)
}
}
}
}
suspend fun add(number: Int): Int { // HOW DO I GET EXCEPTION THROWN HERE?
eventChannel.send(number)
return stateChannel.value
}
init {
Given("we are in initial state") {
currentState shouldBe 0
When("adding 2") {
add(2)
Then("the state should be 2") {
currentState shouldBe 2
}
}
When("trying to add 1") {
Then("we should get an invalid event exception") {
val exception = shouldThrow<InvalidEventException> {
add(1) // THIS IS MY PROBLEM: java.lang.AssertionError: Expected exception CoroutineExceptionTest.InvalidEventException but no exception was thrown.
}
}
}
}
}
}
Colton Idle
12/10/2019, 8:14 AMawait()
a coroutine? I thought I would be able to just define my val result = myRetrofitSuspendingCall
and call await()
on it. It seems like I need to wrap it in an async{}
block before I do, but it seems a little counterintuitive. (I'm still new at coroutines)? Is this async block needed because coroutines themselves still read like synchronous code?Dmitry Khasanov
12/10/2019, 12:10 PMrunBlocking {
suspendCancellableTimeoutCoroutine()
}
2. app doesn't crash
runBlocking {
launch {
suspendCancellableTimeoutCoroutine()
}
}
3. app doesn't crash, but I don't see stacktrace in logcat
runBlocking {
val handler = CoroutineExceptionHandler { _, e -> e.printStackTrace() }
launch(handler) {
suspendCancellableTimeoutCoroutine()
}
}
4. This is the behavior that I have now, it works as needed
runBlocking {
try {
suspendCancellableTimeoutCoroutine()
} catch(e: CancellableException) {
e.printStackTrace()
}
}
Could anyone explain to me 2 and 3, please?Alireza
12/10/2019, 2:55 PMEventBus
? i found this gist: https://gist.github.com/svenjacobs/57a21405b2dda4b62945c22235889d4a , but filter
operator of openSubscription()
is mark as deprecated!, is there any better sample code?akshay_b
12/11/2019, 7:47 AMsuspend fun getStoreMapping(country: String): List<Store> {
return client.getStoreMapping(country).stores
}
Currently, the only option I have is to use different method name, which calls the suspended function in runBlocking {}
like below -
fun getStoreMappingInJava(country: String): List<Store> {
return runBlocking { client.getStoreMapping(country).stores }
}
Kevin Gorham
12/11/2019, 1:14 PMoutput
but the second, similar, example does? No permutation of yield, delay or sleep seems to get output
to print in Example 1.
Example 1 (always prints start stop
):
@Test
fun testUnexpectedBehavior() = runBlocking {
print("start")
captureScope()
scope.launch {
print(" output")
}
print(" stop")
}
lateinit var scope: CoroutineScope
suspend fun captureScope() = coroutineScope {
scope = this
}
Example 2 (always prints `start output stop`:
@Test
fun testExpectedBehavior() = runBlocking {
print("start")
coroutineScope {
launch {
print(" output")
}
}
print(" stop")
}
Alessandro Diaferia
12/11/2019, 3:10 PMCoroutineScope
that works off an IO dispatcher (<http://Dispatchers.IO|Dispatchers.IO>
) and now I’d need to use a class from an external library that is not thread-safe and requires a heavy initialization phase (in the order of a few seconds) per thread. How should I approach this problem? Would I simply initialize one instance and add it to the current CoroutineContext
? How would its access be regulated to make sure there is no concurrent multi-thread access from the various coroutines spread across multiple threads (I assume <http://Dispatchers.IO|Dispatchers.IO>
spans across multiple threads). Any help appreciated.igor.wojda
12/11/2019, 4:23 PMclient A
, client B
). Now client A
calls repository.getUserData()
and this method internally loads data from network. While request is going cliebt B
also calls repository.getUserData()
on the same instance of repository. Can we detekt that network call is in progress and somehow wait for it to finish and return data to both clients?
// Client A:
CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
reository.getUserData()
}
// Client B:
CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
reository.getUserData()
}
class Repository() {
private val job: Job? = null
suspended fun getUserData() {
if(job != null) {
// job is already runned by other client
// can I some how "connect" (wait fo the result) to this job
// instead of proceding and making new network request
}
job = CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
// make network call and return client data
// return network data
}
}
}
David Glasser
12/11/2019, 5:37 PMsuspend
functions where they call other suspend
functions I wrote, so they seem like they may be spurious. Does anyone have any ideas about how to learn more about why these inspections are showing up, to either report a bug or to fix my code if it is in fact bad?Luis Munoz
12/11/2019, 9:44 PMdekans
12/12/2019, 8:14 AMFlow
?
(like Async suffix for the ones returning a Deferred
)Colton Idle
12/12/2019, 9:31 AMval work1 = async { getThingsDone(43) }
val work2 = async { getThingsDoneAgain(123) }
if (work1.await().isSuccessful && work2.await().isSuccessful) {
//do my thing
} else {
//failure message
}
Now with that block above I saw that I was sometimes getting some IOException, and so I wrapped it all in a try/catch.
try {
val work1 = async { getThingsDone(43) }
val work2 = async { getThingsDoneAgain(123) }
if (work1.await().isSuccessful && work2.await().isSuccessful) {
//do my thing
} else {
//failure message
}
} catch (e: IOException){
//network failure message
}
But I still get the IOException. It's as if the try/catch doesn't work.tseisel
12/12/2019, 10:52 AMflow.produceIn(aScope)
, if the source flow terminates with an exception then the produce
coroutines fails and cancels the scope and its parent. Wouldn't it be better if it only cancelled the resulting ReceiveChannel
?John
12/12/2019, 6:46 PMfun suspend getCar(): Car {
val returnedCard
fetcher.getCar({ car ->
returnedCar = car
})
// await while car is fetched ???
return returnedCar
}
Marko Mitic
12/12/2019, 8:34 PMdelay
wait for given real time, not CPU time. I'm assuming that default implementation doesn't take CPU sleep into account, I'm I right? If during 5min delay CPU sleeps for 15 min, will delay effectively take 20min?Patrick
12/13/2019, 8:48 AMPatrick
12/13/2019, 10:05 AMDaniel Lukic
12/13/2019, 10:56 AMime D Shutting down VM
E FATAL EXCEPTION: main
E Process: com.dhl.lps.consumer.debug, PID: 18730
E kotlinx.coroutines.JobCancellationException: Job was cancelled; job=StandaloneCoroutine{Cancelling}@48c8a44
we have scopes like MainScope() + CxExceptionHandler(..)
with launch { .. }
consistently. no async
for now.
so this seems to be some weird/interesting edge case.. 🙂
any pointers on how to track this thing down? 🤔cak
12/13/2019, 11:43 AMcak
12/13/2019, 11:43 AMdiesieben07
12/13/2019, 11:46 AMrepeatInTable
(which is a Swing component) from the IO thread. Swing is not threadsafe.
Then, instead of launching another job using launch
, you can just use
withContext(Dispatchers.Swing) {
}
cak
12/13/2019, 12:48 PM