Andrea Giuliano
10/02/2021, 12:32 PMval results = endpoints.map {
async {
client.call(it)
}
}
results.awaitAll()
but of course that will wait for all the calls to come back, not just the first N.
I know I could solve this problem by using channels and subscribe n topics waiting for them, but I was wondering if there is a counterpart with async/await as well?
Also, as a side note, one thing I’ve noticed is that if the client
is blocking (imagine a Thread.sleep) the async is called sequentially and I lose completely the parallelism..what am I doing wrong?uli
10/02/2021, 4:08 PMuli
10/02/2021, 4:09 PMHusam
10/02/2021, 6:18 PMRavin Jain
10/02/2021, 6:39 PMStylianos Gakis
10/02/2021, 6:48 PMDALDEI
10/03/2021, 3:56 AMtheapache64
10/03/2021, 1:06 PMviewModelScope
controlled SharedFlow
? 🤔
😒tackoverflow: More details: https://stackoverflow.com/questions/69425075/how-do-i-test-sharedflow-controlled-by-a-viewmodelscopemarcinmoskala
10/03/2021, 5:11 PMSlackbot
10/03/2021, 5:11 PMursus
10/03/2021, 5:12 PMActivity {
private val scope = MainScope()
onCreate {
scope.launch {
userDao.user
.collect {
if (it == null) {
resetBackstack()
}
}
}
}
}
SomeScreenViewModel {
private val scope = MainScope()
fun init() {
scope.launch {
userDao.user
.collect {
...
}
}
}
}
UserDao.user
emits on its io dispatcher, both activity and some screen viewmodel are driven by main threaded scope (android)
Occasionally in crashlytics I see crashes related, basically to the fact that the screen collects the emit first
Is there a way I could enforce order of collections?
(I presume if it were a replayed hot Flow, then order would be the order of subscriptions, however I presume that posting to main thread will always be race-y?)int02h
10/04/2021, 9:19 AMkotlin-coroutines-core
different versions. I’ve used resolutionStrategy
Gradle feature to force using the same 1.4.3 version of coroutines but during release build I get the R8 (ProGuard) error like:
ERROR:/Users/*****/***********/app/build/intermediates/module_and_runtime_deps_classes/preliveGooglePlayRelease/base.jar: R8: Type kotlinx.coroutines.debug.AgentPremain is defined multiple times: /Users/*****/***********/app/build/intermediates/module_and_runtime_deps_classes/preliveGooglePlayRelease/base.jar:kotlinx/coroutines/debug/AgentPremain.class, /Users/*****/***********/voip_ui/build/intermediates/module_and_runtime_deps_classes/preliveGooglePlayRelease/feature-voip_ui.jar:kotlinx/coroutines/debug/AgentPremain.class
As I see AgentPremain
indeed contained in both kotlin-coroutines-core
and kotlin-coroutines-core-jvm
with sligtly different byte code. The interesting thing is that kotlin-coroutines-core
introduces the dependency to kotlin-coroutines-core-jvm
according to Gradle dependency graph:
+--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7 -> 1.4.3
| \--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.3
and the POM file says the same:
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core-jvm</artifactId>
<version>1.4.3</version>
<scope>compile</scope>
</dependency>
I wonder how two dependent libraries could have the same class but with different code inside them? Maybe I do something wrong?myanmarking
10/04/2021, 4:27 PM@Test
fun `test flow` (): Unit = runBlocking{
val flow = callbackFlow {
trySend(Unit)
delay(5000)
close()
awaitClose {
println("Closed")
}
}
val job = launch {
flow.collect { }
}
job.cancel()
}
The doc says on close and cancellation. But in this case, it is not called. Why ? When it is cancelled, awaitClose not called.Colton Idle
10/05/2021, 1:35 AM@Singleton
class AppUserManager
@Inject
constructor(@ApplicationContext val context: Context) {
var loggedInFlow = flow<Boolean> { false }
...
and then there is a login call in the appUserManager
fun login(token: String) {
loggedInFlow = flow { true }
...
}
then in my apps ViewModel I listen to this flow via
@HiltViewModel
class HomeScreenViewModel
@Inject
constructor(
var service: ApiService,
private val appUserManager: AppUserManager
) : ViewModel() {
init {
reload()
viewModelScope.launch { appUserManager.loggedInFlow.collect {
reload()
} }
}
...
This doesn't work. I'm assuming I'm missing something fundamental here about how to observe a flow. Any tips for me?rrva
10/05/2021, 8:05 PMnatario1
10/06/2021, 11:15 AMOvsyannikov Alexey
10/06/2021, 12:06 PMMutableSharedFlow
- what shared flow will do in case if nobody is listening for its stream? As I understand, currently all hot flows will throw out data when there are nobody to get it. Or I missed something? If not - is there some built-in flow which allow to prohibit trashing of data in case when nobody listetning that flow?Anshulupadhyay03
10/06/2021, 2:21 PMJustin Tullgren
10/06/2021, 5:51 PMJiri Bruchanov
10/06/2021, 7:08 PMK Merle
10/07/2021, 7:49 AMjulioromano
10/07/2021, 9:31 AMflowOf<Int>(0,1,2,3,4,5,6,7,8,9).magicOperator(2).collect { values: List<Int> ->
print("${values}; ")
}
Would print:
0,1; 1,2; 2,3; 3,4; 4,5; 5,6; 6,7; 7,8; 8,9
Andrew Ebling
10/07/2021, 8:01 PMawait()
(it doesn’t wait 😂 ), where should I start digging? Tried these in `proguard-rules.pro`:
-keepclassmembernames class kotlinx.** {
volatile <fields>;
}
-keepclassmembers class io.ktor.** {
volatile <fields>;
}
-keepclasseswithmembers class io.netty.** {
*;
}
-keepnames class kotlinx.** { *; }
-keepnames class io.netty.** {
*;
}
-keep class io.ktor.** { *; }
-keep class kotlinx.coroutines.** { *; }
-keep class kotlin.reflect.jvm.internal.** {*;}
-keep class kotlin.text.RegexOption {*;}
Danish Ansari
10/10/2021, 8:03 AMandroidTest
source set
Currently I'm testing Room DB Dao in Android and writing test like this
runBlocking {
movieDao.insertCategory(popularMovies)
}
I think that there might be a better way to write test for such scenario because if I have 20 test than I have to write runBlocking
20 timesAmrJyniat
10/10/2021, 6:21 PMdataStore Preference
*synchronously*(one-shot) without delay?ursus
10/12/2021, 4:36 PMprivate suspend fun prefetchStories(stories: List<Story>) {
coroutineScope {
val fetches = mutableListOf<Deferred<Unit>>()
for (story in stories) {
fetches += async {
prefetchStory(story)
}
}
fetches.awaitAll()
}
}
Unsure about the coroutineScope
. Most example don't use it but I presume that means they're using GlobalScope, right?Minsoo Cheong
10/13/2021, 5:31 AMdata class Example(
var fieldA: Int,
var fieldB: Int
)
and that i change fieldA in thread 1 and fieldB in thread 2 (of a same object of class Example). would this be thread-safe? and if not so, how would I achieve thread safety?Jeff Lockhart
10/13/2021, 6:39 AMtrySend()
could.
val flow = callbackFlow {
val job = addListener {
trySendBlocking(it) // unavailable in Kotlin/Native
}
awaitClose {
removeListener(job)
}
}
GUIGAL Allan
10/13/2021, 6:06 PMNino
10/14/2021, 11:01 AMdelay
the emission of values in a flow, during a unit test...
The following code fails :
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.setMain
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class CatRepository(
private val coroutineDispatcher: CoroutineDispatcher
) {
fun getMeowsFlow() = flow {
emit("Meow #1")
delay(3_000)
emit("Meow #2")
}.flowOn(coroutineDispatcher)
}
class CatRepositoryTest {
@get:Rule
val testCoroutineRule = TestCoroutineRule()
private val catRepository = CatRepository(testCoroutineRule.testCoroutineDispatcher)
@Test
fun catShouldMeowOnce() = testCoroutineRule.runBlockingTest {
pauseDispatcher()
assertEquals(
listOf("Meow #1"),
catRepository.getMeowsFlow().toList()
)
}
}
class TestCoroutineRule : TestRule {
val testCoroutineDispatcher = TestCoroutineDispatcher()
private val testCoroutineScope = TestCoroutineScope(testCoroutineDispatcher)
override fun apply(base: Statement, description: Description?) = object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
Dispatchers.setMain(testCoroutineDispatcher)
base.evaluate()
Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
testCoroutineScope.cleanupTestCoroutines()
}
}
fun runBlockingTest(block: suspend TestCoroutineScope.() -> Unit) =
testCoroutineScope.runBlockingTest { block() }
}
It prints
expected:<[Meow #1]> but was:<[Meow #1, Meow #2]>
Expected :[Meow #1]
Actual :[Meow #1, Meow #2]
It makes no sense at all ! Since the virtual time is at 0ms, how come the delay
is completely ignored ? Could someone explain ?Nino
10/14/2021, 11:01 AMdelay
the emission of values in a flow, during a unit test...
The following code fails :
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.setMain
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class CatRepository(
private val coroutineDispatcher: CoroutineDispatcher
) {
fun getMeowsFlow() = flow {
emit("Meow #1")
delay(3_000)
emit("Meow #2")
}.flowOn(coroutineDispatcher)
}
class CatRepositoryTest {
@get:Rule
val testCoroutineRule = TestCoroutineRule()
private val catRepository = CatRepository(testCoroutineRule.testCoroutineDispatcher)
@Test
fun catShouldMeowOnce() = testCoroutineRule.runBlockingTest {
pauseDispatcher()
assertEquals(
listOf("Meow #1"),
catRepository.getMeowsFlow().toList()
)
}
}
class TestCoroutineRule : TestRule {
val testCoroutineDispatcher = TestCoroutineDispatcher()
private val testCoroutineScope = TestCoroutineScope(testCoroutineDispatcher)
override fun apply(base: Statement, description: Description?) = object : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
Dispatchers.setMain(testCoroutineDispatcher)
base.evaluate()
Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
testCoroutineScope.cleanupTestCoroutines()
}
}
fun runBlockingTest(block: suspend TestCoroutineScope.() -> Unit) =
testCoroutineScope.runBlockingTest { block() }
}
It prints
expected:<[Meow #1]> but was:<[Meow #1, Meow #2]>
Expected :[Meow #1]
Actual :[Meow #1, Meow #2]
It makes no sense at all ! Since the virtual time is at 0ms, how come the delay
is completely ignored ? Could someone explain ?Joffrey
10/14/2021, 11:04 AMkotlinx-coroutines-test
, but in any case toList()
would hang forever if the flow
didn't progressNino
10/14/2021, 11:04 AMJoffrey
10/14/2021, 11:05 AMNino
10/14/2021, 11:06 AM@Test
fun catShouldMeow2After3000ms() = testCoroutineRule.runBlockingTest {
advanceTimeBy(3_001)
assertEquals(
"Meow #2",
catRepository.getMeowsFlow().first()
)
}
This test fails too, that's so disappointing 😞Joffrey
10/14/2021, 11:08 AMfirst()
here should return the first element, no matter how long you wait before calling it.ephemient
10/14/2021, 8:10 PMmyanmarking
10/15/2021, 9:40 AMlaunch{flow.toList} delay(x)