aballano
04/04/2022, 12:27 PMSlackbot
04/04/2022, 3:01 PMthe great warrior
04/04/2022, 4:27 PMclass PreferencesManager(private val context: Context) {
...
val selected : Flow<Boolean>
get() = context.counterDataStore.data.map { preferences ->
preferences[AUTO_LOCATION] ?: false
}
}
LocationFragment.kt
class LocationFragment : Fragment() {
...
lifecycleScope.launch {
mainViewModel.autoLocation.collectLatest {
// check if selected
it?.let {
mainViewModel.addPlaceItem(it)
}
}
}
}
MainViewModel.kt
class MainViewModel(
private val application: Application
private val placeRepository: PlaceRepository,
private val preferencesManager: PreferencesManager,
) : ViewModel() {
...
val selected = preferencesManager.selected
}
Robert Jaros
04/04/2022, 5:27 PMsamp
04/04/2022, 8:37 PM* What went wrong:
Execution failed for task ':app:mergeDebugJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
> 2 files found with path 'META-INF/kotlinx_coroutines_core.version' from inputs:
- ../org.jetbrains.kotlinx/kotlinx-coroutines-core/1.6.0/c0277601cc4f7f24fe200651c5680e2e424a0a85/kotlinx-coroutines-core-1.6.0.jar
- ../org.jetbrains.kotlinx/kotlinx-coroutines-core-jvm/1.6.0/f3b8fd26c2e76d2f18cbc36aacb6e349fcb9fd5f/kotlinx-coroutines-core-jvm-1.6.0.jar
Adding a packagingOptions block may help, please refer to
<https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html>
for more information
I am adding this dependency: org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0
I wonder who adds kotlinx-coroutines-core-jvm
version? Is it included under kotlinx-coroutines-core
?Lilly
04/04/2022, 9:54 PMsuspend fun producer() = flow {}
private suspend packetFlow(...): Flow<ResponsePacket> {
return producer()
.transformWhile {
// how to launch coroutine here that does not block?
// coroutineScope {} blocks so it's not an option
launch {
delay(2000L)
state = 1 // set state
return@transformWhile false // terminate flow
}
}
}
I would like to start a timer and terminate the flow after time has expired.Saiedmomen
04/05/2022, 7:03 AMpublic inline fun <reified T, R> combine(
flows: Iterable<Flow<T>>,
crossinline transform: suspend (Array<T>) -> R
): Flow<R> {
val flowArray = flows.toList().toTypedArray()
return flow {
combineInternal(
flowArray,
arrayFactory = { arrayOfNulls(flowArray.size) },
transform = { emit(transform(it)) })
}
}
ildar.i [Android]
04/05/2022, 8:54 AMhfhbd
04/05/2022, 12:01 PMsuspend () -> Unit
, you can create a Continuation
by calling createCoroutine()
. How can you create a CancelableContinuation
?iamthevoid
04/06/2022, 9:43 AMFlow
is stream and shared (state) flow
is hot stream can i somehow sent completion
event through?André Martins
04/06/2022, 4:07 PMsuspend fun getApples(): List<Apple> = ...
suspend fun getPotatos(): List<Potato> = ...
fun work(): ReceiveChannel<SomeResult> = GlobalScope.produce {
try {
val (apples, potatos) = coroutineScope {
val getApples = async {
val (resp, time) = measureTimedValue {
getApples()
}
<http://logger.info|logger.info> { time.inWholeMilliseconds }
resp
}
val getPotatos = async {
val (resp, time) = measureTimedValue {
getPotatos()
}
<http://logger.info|logger.info> { time.inWholeMilliseconds }
resp
}
getApples.await() to getPotatos.await()
}
send(doSomething(apples, potatos))...
} catch(ex: Exception) {
handle...
}
}
samp
04/06/2022, 11:25 PMval dispatcher = StandardTestDispatcher()
val scope = TestScope(dispatcher)
@Test
fun testFoo() = runTest(dispatcher) {
// ...
}
vs
val dispatcher = StandardTestDispatcher()
val scope = TestScope(dispatcher)
@Test
fun testFoo() = runTest {
// ...
}
what if i don’t pass the dispatcher, I know it will default to StandardTestDispatcher
but wouldn’t be those two different dispatcher
here?
1. created by runTest
2. created by dispatcher
propertyQuantum64
04/07/2022, 2:38 AMclass KeyedMutex<T> {
@PublishedApi
internal val mutexes = ConcurrentHashMap<T, Container>()
data class Container(
val mutex: Mutex,
val holders: Int
)
suspend inline fun <U> use(key: T, closure: () -> U): U {
val result = mutexes
.compute(key) { _, container ->
container?.copy(holders = container.holders + 1)
?: Container(Mutex(), holders = 1)
}!! // always associates the key
.mutex
.withLock(action = closure)
mutexes.computeIfPresent(key) { _, container ->
if (container.holders > 1) container.copy(holders = container.holders - 1)
else null
}
return result
}
}
Omar Qadour
04/07/2022, 5:11 PMsamp
04/07/2022, 7:23 PMUnconfinedTestDispatcher
and advance the coroutines automatically?
or
Use StandardTestDispatcher
and manually execute the jobs?
Do we have any recommendations from the official docs?Sam Stone
04/10/2022, 7:29 PMoverride fun onProgress(Int)
. Can I use a Flow for this?darkmoon_uk
04/11/2022, 8:22 AMWilliam Reed
04/11/2022, 12:24 PMConnected
and Disconnected
as a StateFlow
. I am trying to add more states such as Connecting
or LookingForSavedDevice
at a higher level in my program so I would like to use a StateFlow
which both takes in emissions from the library functions as well as allow me to mutate the StateFlow
myself.
So I think I'm looking for a way to collect into another flow:
bluetoothLibrary.stateFlow.collect(myOtherStateFlow)
I'm aware I can just emit into the new flow in a collect { }
block or onEach { }
but I'm not sure what is canonicalAlexander Maryanovsky
04/11/2022, 12:33 PMSequence
. How do I make this computation properly cancelable? All the Sequence functions are non-suspending, and the coroutine context is not available in a non-suspending function, so I can’t check for isActive
. Can I capture the coroutine context in the outermost (suspend) function and pass it into all the (non-suspending) sequence functions?juliocbcotta
04/12/2022, 12:32 PMrunBlocking(Dispatchers.Main.immediate) {
initialize(application)
}
suspend fun initialize(app: Application) = coroutineScope {
registry.groupBy { initializer ->
initializer.priority().ordinal
}
.toSortedMap()
.forEach { entry ->
val tasks = entry.value.map { initializer ->
async {
initializer.initialize(app)
}
}
tasks.awaitAll()
}
}
The code above runs, but if I change
async {
to
async(Dispatchers.Default) {
Makes the app blocks forever. Would anyone have an idea of how to fix it ?martmists
04/12/2022, 2:24 PMJi Sungbin
04/13/2022, 12:31 AMfun main() = runBlocking {
delay(1000)
println("Bye, world!")
}
If decompile its bytecode into Java, will get the following output:
public final class MainKt {
public static final void main() {
BuildersKt.runBlocking$default((CoroutineContext)null, (Function2)(new Function2((Continuation)null) {
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch (this.label) {
case 0:
ResultKt.throwOnFailure($result);
this.label = 1;
if (DelayKt.delay(1000L, this) == var3) {
return var3;
}
break;
case 1:
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
String var2 = "Bye, world!";
System.out.println(var2);
return Unit.INSTANCE;
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkNotNullParameter(completion, "completion");
Function2 var3 = new <anonymous constructor>(completion);
return var3;
}
public final Object invoke(Object var1, Object var2) {
return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 1, (Object)null);
}
}
If the function end with return var3
in case 0:
in the code above, there should be a code that can enter the function again. I opened runBlocking and delay but couldn’t find it. Where are giving code to continue with label 1 ?
(Sorry for the long code snippet)enighma
04/13/2022, 8:27 AMMartin Rajniak
04/13/2022, 8:52 AMdelay
sometimes takes 30m instead of expected 4m (that were supplied as argument)?
It is observed on Android.hfhbd
04/13/2022, 10:35 AMAmbiguous coroutineContext due to CoroutineScope receiver of suspend function
, because CoroutineScope.coroutineContext
and coroutineContext
. But why does coroutines-core itself use this construct? https://github.com/Kotlin/kotlinx.coroutines/blob/52cbf01c63c0737ee745ff08568f26385271a9ab/kotlinx-coroutines-core/common/src/Builders.common.kt#L50Tom Everton
04/13/2022, 11:38 AMclass Outer : Closeable {
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
private var inner: Inner? = null
fun startInner() {
inner = Inner(InnerRepo(), InnerApi())
}
fun stopInner() {
inner.close()
inner = null
}
override fun close() {
scope.cancel()
}
... // More code that uses the outer scope
}
And in the inner I have some code that calls suspend functions:
class Inner(
private val repo: InnerRepo,
private val api: InnerApi
) : Closeable {
private val innerScope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + SupervisorJob())
fun sendData() {
innerScope.launch {
api.sendData(repo.getData())
}
}
override fun close() {
innerScope.cancel()
}
}
Is there a way to link the innerScope
to the outerScope
as it makes sense that the innerScope
would always want to be cancelled if the outer scope cancels, or is that even something that should be done? Also, if the pattern above is completely wrong let me know!
CheersNick Williams
04/13/2022, 11:46 AMsuspend fun main() {
coroutineScope {
flowOf<Unit>().shareIn(this, SharingStarted.WhileSubscribed())
}
}
https://pl.kotl.in/gaJVXPMWr = Evaluation stopped while it's taking too long️. Why? The child coroutine of shareIn should, according to docs, never startLukasz Kalnik
04/13/2022, 2:24 PMcancelAllChildren
of a runTest
scope?
I have a test where I inject the test coroutineContext
into a ViewModel and I want to cancel all running jobs inside the ViewModel when the test ends.Sanat Tripathi
04/13/2022, 6:21 PMmap.toMap()
to happen atomically. I wanted to see whether something exists before creating my own synchronization blocks.Ananiya
04/14/2022, 3:58 AMsuspend fun get() = stateChannelFlow(viewModelScope){firebase.database./**some stuff*/.get.addOnSuccessListener { data ->
viewModelScope.launch {
send(data)
}
}
}
ik, you could say you should have used stateFlow instead ofstateChannelFlow I did but it forced me to use channel over regular flow
btw called this function in Fragment() lifecycleScope
at this time i have no idea if I messed the coroutine thing on get() but i tried my best trying d/n things which failed
N: this is the code for the extension function
suspend fun <T>stateChannelFlow(scope: CoroutineScope, @BuilderInference block: suspend ProducerScope<T>.() -> Unit): StateFlow<T> = channelFlow(block).stateIn(scope)
Ananiya
04/14/2022, 3:58 AMsuspend fun get() = stateChannelFlow(viewModelScope){firebase.database./**some stuff*/.get.addOnSuccessListener { data ->
viewModelScope.launch {
send(data)
}
}
}
ik, you could say you should have used stateFlow instead ofstateChannelFlow I did but it forced me to use channel over regular flow
btw called this function in Fragment() lifecycleScope
at this time i have no idea if I messed the coroutine thing on get() but i tried my best trying d/n things which failed
N: this is the code for the extension function
suspend fun <T>stateChannelFlow(scope: CoroutineScope, @BuilderInference block: suspend ProducerScope<T>.() -> Unit): StateFlow<T> = channelFlow(block).stateIn(scope)
gildor
04/14/2022, 4:00 AMstojan
04/14/2022, 8:34 AMcallbackFlow
is the way... here is an example:
https://piotrprus.medium.com/use-kotlin-coroutines-for-firebase-real-time-database-streams-e28d6083709cgildor
04/14/2022, 9:33 AMAnaniya
04/14/2022, 3:51 PMstateFlow
which was quite nice
However it wasn't working as I wanted it
I was expecting it to update the UI with stream of data changegildor
04/16/2022, 2:15 AMI was expecting it to update the UI with stream of data changeMaybe they have flow adapter? If they don’t you can write own with callbackFlow