Paul Woitaschek
11/24/2020, 8:16 AMimport kotlinx.coroutines.runBlocking
fun main() {
val getTrainingEmoji = GetTrainingEmoji()
runBlocking {
getTrainingEmoji()
}
}
inline class Emoji(val value: String)
class GetTrainingEmoji {
suspend operator fun invoke(): Emoji {
return Emoji("hello")
}
}
wbertan
11/24/2020, 3:34 PMStateFlow
to handle a kind of Event
, but facing issues when trying to set the same value again (for example when the user clicks the same button again, triggering same event).
Found this GitHub issue: https://github.com/Kotlin/kotlinx.coroutines/issues/2011
With @elizarov comment:
We'll provide a different, more flexible primitive, for those rare cases when you don't want equality-based conflation. Stay tuned.
Do we have anything in the latest release to handle this scenario?André Thiele
11/24/2020, 4:19 PMFlorian
11/24/2020, 5:27 PMinline fun <reified T> Query.asFlow() = callbackFlow<List<T>> {
val registration = addSnapshotListener { snapshot, error ->
if (error != null) {
cancel(CancellationException("Query snapshot error", error))
}
offer(snapshot?.toObjects(T::class.java) ?: emptyList())
}
awaitClose { registration.remove() }
}
myungpyo.shim
11/25/2020, 4:39 AMfun main(): Unit = runBlocking {
launch {
//CASE 1 : Will make the application main thread crash
val result = returnAsKotlinResultFunc()
//CASE 2 : Will not make the application main thread crash
// val result = returnAsValueFunc()
println("Return value : $result")
}.join()
}
suspend fun returnAsKotlinResultFunc(): Result<String> = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
val result = runCatching {
delay(100)
throw IllegalStateException()
}
result
}
suspend fun returnAsValueFunc(): String = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
val result = runCatching {
delay(100)
throw IllegalStateException()
}
"Result : $result"
}
returnAsKotlinResultFunc
makes the application crash. seems like It can't catch the exception. On the other hand, returnAsValueFunc
can normally handle the exception and return the String result.
I think the return type is the only different thing they have.
Have I missed something on it?
(I am using below compiler options to return Result type.
kotlinOptions {
freeCompilerArgs = [
"-Xallow-result-return-type",
//"-Xexplicit-api=strict"
]
}
Mark
11/25/2020, 8:48 AMcollect()
vs collectLatest()
: I see the docs for collectLatest()
say: when the original flow emits a new value, action block for previous value is cancelled.
But specifically for StateFlow
just about all the examples I see use collect()
. So I’m wondering if the decision whether to use collect()
or collectLatest()
can/should be made on the basis of the nature of the action block (for example, an action block of non-suspending code I suppose the choice is irrelevant - or more generally, is there a problem with cancelling the action block before completion) or whether the nature of StateFlow
also impacts the decision somehow?aleksey.tomin
11/25/2020, 3:46 PMSuspendFunctionGun
(Code deeper is intrinsic).
I thin it’s a coroutines problem: https://youtrack.jetbrains.com/issue/KT-43589ursus
11/25/2020, 8:19 PMleandro
11/25/2020, 8:37 PMleandro
11/25/2020, 8:39 PMursus
11/25/2020, 11:35 PMursus
11/25/2020, 11:36 PMprivate fun generateMac(someUuid: String, base16HexStringKey: String): String {
val uuidIdBytes = someUuid.toByteArray(UTF_8)
val keyBytes = base16HexStringKey.toHexByteArray().decodeBase16()
return hmacSha512(uuidIdBytes, keyBytes).encodeBase16().toHexString()
}
It just generates hmac of some uuid string ... worth suspending?Kurt Renzo Acosta
11/26/2020, 6:55 AMprivate val _myFlow = MutableStateFlow<String?>(null)
val myFlow: Flow<String> get() = _myFlow.filterNotNull()
But I want to expose the flow as a StateFlow
to the consumer. I can use asStateFlow()
but I can’t use filterNotNull()
anymore as it converts it back to a Flow
df
11/26/2020, 5:01 PMfun getContent(dropN: Long) = flow {
val counter = AtomicLong(dropN)
val resource = javaClass.getResource("/products.csv").toURI()
File(resource).useLines { lines ->
lines.filter { it.isNotEmpty() }
.drop(dropN.toInt())
.map { it.toLong() }
.chunked(100)
.onEach { counter.addAndGet(it.size.toLong()) }
.map { getContentByProductIds(it) }
.onEach { println("Processed ${counter.get()} lines from input file") }
.forEach { emit(it) }
}
}
The flow is collected by multiple co-routines and I see exactly the same lines printed multiple times.
Processed 100 lines from input file
Processed 100 lines from input file
Given the flow definition I would assume the second onEach should only be invoked when the first onEach was invoked before, which should always increment the counter. Why do I still see the same counter value multiple times?aleksey.tomin
11/27/2020, 7:23 AMwhy
11/27/2020, 2:57 PMkotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.collections.HashMap@dac14b48
Basically I have a static hashmap to serve caching purposes, since KMP doesn’t have a ConcurrentHashMap -yet, right?- I’m testing using a normal hashmap and reentrantLock() from kotlinx.atomicfu, the hashmap is static - in companion object{} - it always fails in native when you try to put something in itAjaydeepak07
11/28/2020, 1:20 PMdf
11/29/2020, 4:56 PMclass SomeClass { fun CoroutineScope.producer() = produce { ... } }
or is it
class SomeClass { fun producer(scope: CoroutineScrope) = scope.produce { ... } }
or should (for some reasons) those methods never be methods but just functions? If it's the first one, do I really need to invoke it via
with(obj) { producer() }
? If it's second one, do I just want to pass in this
? Might sound random but I still find myself frequently in a situation where I know how something can be done but never why.Roshan P Varghese
11/29/2020, 4:59 PMkelvinharron
11/30/2020, 11:22 AMnative-mt
makes a difference when used in a standard kotlin android project? We see native-mt
bumps occasionally like (kotlinCoroutinesVersion from 1.4.1 to 1.4.2-native-mt) and as I understand it, native-mt
enables multithreaded coroutine support on Kotlin native projects only. One to ignore in our use case? Thanks in advance.bbaldino
11/30/2020, 5:41 PMCoroutingScope#onFinish
helper which delayed wrapped an indefinite delay in a try/finally and called a cleanup method in the finally
block, but it feels wrong).
Of these, I think #2 is the biggest sticking point: I find myself wishing I could create a child coroutine scope but wait for any child to finish, instead of all children to finish (like coroutineScope
and runBlocking
do). Does that exist?allan.conda
11/30/2020, 5:46 PMByron Katz
11/30/2020, 6:43 PMbbaldino
11/30/2020, 10:02 PMval task = myScope.async { ... }
, and then I wait on those deferreds in a select
block. When a task throws, most of the time the exception I catch (around my select) is the actual exception thrown by the task. But sometimes it's a JobCancellationException
with the cause being the actual exception. Is that expected? Or is there something weird going on there?Florian
12/01/2020, 6:58 AMinvokeOnCompletion
a good place to hide a progress bar if a Coroutine was either finished or cancelled?
.invokeOnCompletion {
_loading.postValue(false)
}
ubu
12/01/2020, 1:45 PMfun someFun() {
val job1 = viewModelScope.launch { operation1() }
val job2 = viewModelScope.launch { operation2() }
}
Are these two operations sequential by default? Operation in the first launch block is completed, and only then, the second operation is started.Kevin M Granger
12/01/2020, 5:47 PMsuspend fun
out of a home-grown coroutine?
Suppose I have some computation-heavy code that has some natural "pause" points. I'd like to use existing coroutine tools to handle cancellation and timeouts-- but everything expects you to use a suspend
function.
In other words, I more or less have this:
sealed class ComputationResult {
abstract fun finish(): Int
class Finished(val result: Int) : ComputationResult() {
overide fun finish() = result
}
class InProgress(val rest: Computation) : ComputationResult() {
override fun finish() = rest().finish()
}
}
// does not currently implement Continuation<Unit> but could easily do so
class Computation {
operator fun invoke(): ComputationResult {
TODO()
// implementation elided here, but it could easily check
// to see if it was cancelled
}
}
Can I turn it into suspend fun compute() -> Int
?bbaldino
12/01/2020, 6:33 PMval t = scope.async { ... }
val u = scope.async { ... }
try {
select<Unit> {
t.onAwait { ... }
u.onAwait { ... }
}
} catch (c: CancellationException) {
...
} catch (t: Throwable) {
...
}
where scope
is not cancelled anywhere and one of the t
, u
tasks throws an exception, should I always be able to catch the exception that was thrown in my block? I'm seeing that most of the time I get the exception thrown by t
or u
, but sometimes I get a CancellationException
wrapping the exception thrown by t
or u
and I'm trying to figure out if this is to be expected when using select
or if I'm doing something wrong.spierce7
12/02/2020, 4:13 AMList<Flow<String>>
and I want to merge them all into a single Flow<String>
, what’s the best way to do that?spierce7
12/02/2020, 4:24 AMCoroutineContext
via coroutineContext
, what is the best way for me to create child coroutines? I’m assuming I need to create a CoroutineScope
, but there aren’t any utility methods I’ve found for this, making me think that there might be a better way?spierce7
12/02/2020, 4:24 AMCoroutineContext
via coroutineContext
, what is the best way for me to create child coroutines? I’m assuming I need to create a CoroutineScope
, but there aren’t any utility methods I’ve found for this, making me think that there might be a better way?Zach Klippenstein (he/him) [MOD]
12/02/2020, 4:48 AMcoroutineScope {}
. Otherwise, you can use CoroutineScope(coroutineContext)
spierce7
12/02/2020, 4:57 AMcoroutineScope {}
. It doesn’t look like it uses the current scope. If I call coroutineScope {}
inside a coroutine, will it create child coroutines?bezrukov
12/02/2020, 6:31 AMZach Klippenstein (he/him) [MOD]
12/02/2020, 5:21 PM