Robert Jaros
02/13/2021, 1:28 AMMutableStateFlow<S>
from MutableStateFlow<S?>
?WukongRework.exe
02/13/2021, 5:02 AMwithTimeout
function and found that if I put a loop, it does not trigger the timeout cancellation exception but if I use a delay statement for the same amount of time, then it triggers the catch block. Could anyone explain why?Alex Vasilkov
02/14/2021, 7:25 AMMutex
, but it is very slow, if you’ll run the examples from https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html you’ll notice that Mutex
is like 100 times slower than atomics.
I found a way to use MutableStateFlow<Boolean>
for suspending calls synchronization and it seems to be 5-10 times faster than Mutex
, I’m not sure if there are any hidden gotchas with this approach though (see more in the thread).Nick Williams
02/14/2021, 2:45 PMWill Mwendwa
02/15/2021, 6:55 AMSergey Skaredov
02/15/2021, 3:07 PMadambl4
02/16/2021, 7:22 AMWill Mwendwa
02/16/2021, 9:40 AMPablo
02/16/2021, 4:02 PMsuspendCancelableCoroutine{..}
? Then do i need the launch{}
somewhere? Or from the java class I call the method of my presenter and that's it? I can avoid the launch?Ben Madore
02/16/2021, 6:57 PMrsetkus
02/18/2021, 12:43 PM@Test
fun testSuccess() = runBlocking {
val repository = Repository()
var actual: String? = null
val job = repository.getData(TEST_URL) {
actual = it
}
job.join()
assertEquals(TEST_MESSAGE, actual)
}
Repository getData function:
fun getData(
url: String,
callback: (String) -> Unit = {}
): Job {
return GlobalScope.launch(dispatcher) { // Dispatchers.Main (Android), NsQueueDispatcher (iOS)
try {
val message: String = httpClient.request(...)
callback(message)
} catch (e: Exception) {
println("Exception: $e")
}
}
}
Test passes running for Android platform but getting infinite loop for iOS platform. Does anybody know a good way to test a callback function which was invoked within coroutine? Any help much appreciated. 🙏🏻Bradleycorn
02/18/2021, 4:36 PMSimplePoller
class that will run a block: suspend () -> Unit
on a given interval. it looks like this (code condensed a bit for posting in Slack):
class SimplePoller(private val interval: Long, private val block: suspend () -> Unit) {
private var job: Job? = null
fun start(scope: CoroutineScope) {
if (job == null || job?.isCompleted == true) {
job = scope.launch {
while (isActive) {
try {
block()
delay(interval)
} catch (ex: Exception) { cancel() } // stop on errors
}
}
}
}
fun stop() {
job?.let { if (it.isActive) it.cancel() }
}
}
Most of the time, it's used to poll the block
while some Android Lifecycle
is in a certain state. For example:
val myPoller = SimplePoller(60_000) {
//do some work that needs to be repeated like call a network api, etc
}
lifecycleScope.launch {
whenResumed {
myPoller.start(this)
}
}
Inside the poller, I launch a new job in the passed in scope so that I can "manually" (via a call to stop()
) stop the polling if necessary.
Does this seem like a good approach?
It seems to work pretty well. In testing the poller runs while the lifecycle is resumed, and suspends (because the passed in scope uses a magical Android "PausingDispatcher") when lifecycle < resumed. It also seems flexible enough that I could really use it in other, non-android-lifecycle situations:
someScope.launch {
myPoller.start(this)
}
// And then sometime later:
myPoller.stop()
I don't see anything immediately wrong, but as I mentioned, I'm still new to coroutines, so... 🤷Florian
02/18/2021, 4:47 PMlauch
inside a channelFlow
, what coroutine scope is used for that channelFlow
? The one that collects from the channelFlow
?zak.taccardi
02/18/2021, 7:57 PMService
in Android? We’re currently using override fun onHandleWork(intent: Intent)
in a JobIntentService
and I was wondering if there was a more idiomatic way to make that function Coroutine friendly, as opposed to using runBlocking { }
in thereCiprian Grigor
02/18/2021, 8:41 PMAndrew Ebling
02/19/2021, 9:52 AMoverride fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId) {
R.id.refresh -> {
flow {
callbacks?.refreshAllTheThings()
}.debounce(5000)
return true
}
else -> {
return super.onOptionsItemSelected(item)
}
}
}
...however I get the following compilation error: Not enough information to infer type variable T
I’ve gone and looked at the implementation of debounce()
but the examples in the comments suggest what I have above should be sufficient.
Why does flow need type information if I just want to execute one line of code, at most, every 5 seconds?spierce7
02/19/2021, 6:01 PMrocketraman
02/19/2021, 7:54 PMStateFlow
, is it safe to access the current state inside a catch
block?samuel
02/19/2021, 11:09 PMreplaceState
works as expected with the subscriber getting the new value, however, calling updateState
doesn’t. Does any one have a clue why this happens?Dominaezzz
02/20/2021, 2:38 PMRan
02/21/2021, 3:24 AMkotlinx-coroutines-test
library to test my coroutines code. But after I used TestCoroutineDispatcher
to mock the dispatcher, the coroutine resumed continually until throw an exception with the message:
kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[TestCoroutineDispatcher[currentTime=0ms, queued=0], Continuation at xxx.viewmodel.CarListViewModel$loadCars$1.invokeSuspend(CarListViewModel.kt)@1da6ee17]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
You can find the specific code at https://youtrack.jetbrains.com/issue/KT-45088.darkmoon_uk
02/21/2021, 4:40 AMStylianos Gakis
02/21/2021, 9:47 PMCLOVIS
02/22/2021, 3:53 PMwithContext(<http://Dispatchers.IO|Dispatchers.IO>) {
foo()
}
is conceptually equivalent as this one:
launch(<http://Dispatchers.IO|Dispatchers.IO>) {
foo()
}.join()
Since the implementation is very different, I expect that for performance reasons it does something else, but as a developer should I use withContext
as syntax sugar for launch().join()
, or is there something else I need to know about?Ivan
02/23/2021, 7:17 AMLucien Guimaraes
02/23/2021, 12:40 PMThis job has not completed yet
Here is my implementation:
class MyUseCaseImpl(
myRepository: MyRepository,
myID: String,
ioDispatcher: CoroutineDispatcher,
) : MyUseCase {
override val state = MutableStateFlow<MyState>(MyState.Loading)
init {
CoroutineScope(ioDispatcher).launch {
myRepository
.requestStuff(myID)
.map { MyState.Success(it) }
.catch { state.emit(MyState.Error(it)) }
.collect { state.emit(it) }
}
}
}
interface MyUseCase {
sealed class MyState {
object Loading: MyState()
data class Error(val throwable: Throwable) : MyState()
data class Success(val hikeTrack: HikeTrackResponse) : MyState()
}
val state: Flow<MyState>
}
And here is the UT failing:
...
private val coroutineDispatcher = TestCoroutineDispatcher()
...
@Test
fun `Given ... `() = coroutineDispatcher.runBlockingTest {
When calling myRepository.requestStuff(myID) `it returns` flowOf(stuffResponse)
val myUseCase = MyUseCase(
myRepository,
myID,
coroutineDispatcher,
)
myUseCase.state.take(2).toList() shouldBeEqualTo listOf(
MyState.Loading,
MyState.Success(stuffResponse),
)
}
}
From the documentation it says If the test needs to check multiple values, calling toList() causes the flow to wait for the source to emit all its values and then returns those values as a list. Note that this works only for finite data streams
. For what I understand, the UT fails because the flow I'm returning to my repository is an infinite streams. But shouldn't flowOf(value)
create a finite stream ?
Thanks !Michal Klimczak
02/23/2021, 7:12 PMursus
02/24/2021, 5:46 AMMutex
suitable to be used at business logic level for example in sendChatMessage()
to keep them sequential?Thiago
02/24/2021, 3:35 PMreceiveAsFlow
to transform a Channel in Flow. After cancel the CoroutineScope where I'm collecting the Channel values it seems not have closed the Channel. Can be codes like below create leaks without call close()
?
Should I add a call to invokeOnCompletion
to make sure that close my Channel as:
invokeOnCompletion {
channel.close()
}
Kshitij Patil
02/25/2021, 9:52 AMconflate
on Flow<T>
and using StateFlow<T>
?
Also, why can’t I just get a StateFlow
when I use map
on existing StateFlow
?Kshitij Patil
02/25/2021, 9:52 AMconflate
on Flow<T>
and using StateFlow<T>
?
Also, why can’t I just get a StateFlow
when I use map
on existing StateFlow
?streetsofboston
02/25/2021, 12:55 PMZach Klippenstein (he/him) [MOD]
02/25/2021, 4:02 PMKshitij Patil
02/25/2021, 6:06 PMstate.map{ }.stateIn(scope)
?Zach Klippenstein (he/him) [MOD]
02/25/2021, 6:15 PM