Eric Ampire [MOD]
10/30/2020, 12:56 PMLiveData
and StateFlow
.
class DownloadingModel {
private val _state = MutableStateFlow<DownloadStatus>(DownloadStatus.NOT_REQUESTED)
val state: StateFlow<DownloadStatus> get() = _state
suspend fun download() {
_state.value = DownloadStatus.INITIALIZED
initializeConnection()
processAvailableContent {
partialData: ByteArray,
downloadedBytes: Long,
totalBytes: Long
->
storePartialData(partialData)
_state = DownloadProgress(downloadedBytes.toDouble() / totalBytes)
}
_state.value = DownloadStatus.SUCCESS
}
}
Shawn Witte
10/30/2020, 11:37 PMsuspend
function, I usually wrap the launch
or async
call with withContext
(although, it looks like I should be using coroutineScope
a little more often). This will tie the new coroutines into the structured concurrency of the calling coroutine, which is all fine and dandy.
On the other hand, suppose I had something along the lines of
shortLivedScope.launch {
// some stuff
longLivedScope.launch { performSomeTasks() }
// some stuff
}
What is the relationship between the coroutines I have now launched?florent
10/31/2020, 11:27 AMResult.UiUpdate.MovieList
is a sealed class. Do you know why I have to add as Result and the compiler want me to remove it?natario1
10/31/2020, 1:02 PMval flow = MutableStateFlow<Boolean>(false)
, How to write a function that suspends until the flow value is true for the first time?
suspend fun waitUntilTrue() { ... }
rkeazor
11/01/2020, 1:32 PMGrantas33
11/01/2020, 4:08 PMLalit Sagar
11/02/2020, 8:14 AMsuspendCancellableCoroutine
. It mentions that this function throws a CancellationException
if the coroutine is cancelled or completed while suspended.
In which case the coroutine is completed while suspended?william
11/03/2020, 2:03 AMUncaught Kotlin exception: kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[WorkerCoroutineDispatcherImpl@169bc08, Continuation @ $start$lambda-1COROUTINE$34]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
...
Caused by: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen dev.williamreed.clique.mobile.WsSession.$start$lambda-1COROUTINE$34@3b34238
is this actually a bug in the library - or is the fault the "caused by" section from something I did?jean
11/03/2020, 7:48 AMStateFlow
contains this statement:
So a slow collector skips fast updates, but always collects the most recently emitted value.What’s the actual threshold that makes it skip states? Do I need to add a
delay
call if I want to force some State to NOT be skipped?Pablo
11/03/2020, 2:46 PMDavide Giuseppe Farella
11/03/2020, 5:29 PMfun login(): Flow<LoginState>
sealed class LoginState {
object Loading : LoginState()
class ApproveRequestToken(val url: String) : LoginState()
object Completed : LoginState()
}
When the LoginState.ApproveRequestToken
is emitted, I have to wait for user interaction ( approve token via web ), then I want the Flow
to continue, what would be your best approach?Erik
11/03/2020, 7:03 PMSingleLiveEvent
(Android pattern when using view models and live data) be modeled using flows?
I think that the documentation of fun <T> ReceiveChannel<T>.receiveAsFlow(): Flow<T>
(https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/receive-as-flow.html) describes this specific use case:
Represents the given receive channel as a hot flow and receives from the channel in fan-out fashion every time this flow is collected. One element will be emitted to one collector only.So, if I just create a
private val _events = Channel<MyEvent>()
in my ViewModel
and expose it as val events = _events.receiveAsFlow()
, would that behave like a single live event? I.e.: one collector only receives the event, all others don't? Or are there additional things to consider? I'm a bit confused about the existence of (Mutable)SharedFlow
(and the now obsolete BroadcastChannel
), but I think this will always share emissions between all active collectors (subscribers) and that's precisely what single live event tries to prevent, am I right?Erik
11/03/2020, 7:34 PMTestCoroutineScope
/ -Dispatcher
with runBlockingTest
, when you flow.launchIn(testScope)
, then the job would leak unless you remember to cancel the job before the test block ends. How can you verify more easily that a flow emitted certain values? I can think of some solutions:
1. As a side effect, put collected values in some mutable collection. This makes assertion of values easy, but you still have to remember to cancel any collectors of the uncompleted flow.
2. Cancel the source of the flow, i.e. force it to complete, by the end of the test. This should usually also complete collectors.
3. Do not use the test coroutine scope to collect flows that do not complete. This has a downside that you test with multiple scopes, which may be conceptually challenging.
Either way it's a bit of test boilerplate 👎 Any ideas?octylFractal
11/04/2020, 2:53 AMInappropriate blocking method call
always appearing, even if wrapped in <http://Dispatchers.IO|Dispatchers.IO>
?Circusmagnus
11/04/2020, 8:12 AMfun constructFlow() = flow { for(x in channel) emit(x) }
Is there any practical difference between
val someFlow = constructFlow()
and
val someFlow get() = constructFlow()
?
I do realize, that second version will call constructFlow on every access, while first one - only once. But since a flow is only a definition of what should happen after collection - isn`t it always the same?Orhan Tozan
11/05/2020, 1:47 PMchatConversationsFlow: Flow<List<ChatConversation>>
to a lastMessagesFlow: Flow<List<String>>
.
When the last message of a conversation is sent by me, the result will be of the format "You: ${chatConversation.lastMessage}"
.
But when the last message of a conversation is sent by someone else than me, I first need to get userFlow: Flow<User>
of the specific user, then the result will be of the format "${user.name}: ${chatConversation.lastMessage}"
.
What would be the best (preferably most idiomatic) approach to achieve this in Flow/Coroutines?
private fun lastMessagesFlow(
chatConversationsFlow: Flow<List<ChatConversation>>
): Flow<List<String>> = flow {
emit(listOf("Loading"))
emitAll(
chatConversationsFlow.map { chatConversations ->
chatConversations.map { chatConversation ->
if (chatConversation.lastMessageSentByUserId == -1) "You: ${chatConversation.lastMessage}"
else {
val userFlow: Flow<User> = userFlow(userId = chatConversation.lastMessageSentByUserId)
userFlow.map { user ->
"${user.name}: ${chatConversation.lastMessage}"
}
}
}
}
)
}
rsetkus
11/05/2020, 3:17 PM> Could not find org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.4.1.
Searched in the following locations:
- <https://dl.google.com/dl/android/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-native/1.4.1/kotlinx-coroutines-core-native-1.4.1.pom>
- <https://jcenter.bintray.com/org/jetbrains/kotlinx/kotlinx-coroutines-core-native/1.4.1/kotlinx-coroutines-core-native-1.4.1.pom>
- <https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-native/1.4.1/kotlinx-coroutines-core-native-1.4.1.pom>
Latest I can sync is 1.3.8
Used remote repositories:
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
rkeazor
11/06/2020, 6:50 AMTomasz Krakowiak
11/06/2020, 7:03 AMPablo
11/06/2020, 11:16 AMandylamax
11/07/2020, 12:34 AMkotlinx-coroutines-compose
With dedicated dispatchers for composables
launching suspending functions?WukongRework.exe
11/07/2020, 2:23 AMShalom Halbert
11/07/2020, 8:30 AM9a
9b
9c
9d
9e
9fwhen it seemingly should be printing
1a
2a
3a
4a
5a
6a
7a
8abefore that?
@Test
fun example1(): Unit = runBlocking {
val flowA = flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val flowB = flowOf("a", "b", "c", "d", "e", "f").onEach { delay(1000) }
flowA.combine(flowB) { a, b -> "$a$b" }.collect { println(it) }
}
Luke
11/07/2020, 7:38 PMStateFlow<T>
to a StateFlow<R>
? I have a MutableStateFlow<MyEnum>
in a view model, but I want it private to expose publicly a StateFlow<String>
Bruno Ortiz
11/08/2020, 3:18 PMfun receive(interval: Duration) = flow {
while (true) {
delay(interval.toMillis())
val messages = getMessages(interval)
messages.forEach {
println("Emitting $it")
emit(it)
}
}
}
I can consume the flow "forever" like this:
receive(Duration.ofSeconds(1))
.collect {
println(it)
}
Or limit the number of messages that i consume:
val amount = 10
receive(Duration.ofSeconds(1))
.take(amount)
.collect {
println(it)
}
I tested this and the flow "completes", but i do not understand what happens in the second case, do the while(true)
loop gets suspended forever? Is this a problem?Brendan Weinstein
11/08/2020, 5:16 PMnative-mt
variant of coroutines 1.4.1?Slackbot
11/09/2020, 11:38 AMgsala
11/09/2020, 12:00 PMCoroutineScope
to a function, instead of making the function suspendable and then call coroutineScope {}
inside?
What I'm going for:
fun connect(
device: BluetoothDevice,
connectionScope: CoroutineScope,
): StateFlow<BleConnectionState>
I want to have the consumers of this API decide what the lifetime/scope of the BLE connection should beYuri
11/09/2020, 3:37 PMCore
:
CoroutineExceptionHandler {...} + SupervisorJob() + Dispatchers.Default
UI
:
coreContext + (several custom elements holding activity reference) + Dispatchers.Main.immediate + SupervisorJob(coreContext[Job])
Let’s say I have
// core level
class CoreModel(coreScope: CoroutineScope) {
suspend fun operation(): Result {???}
}
// ui level
uiContext.launch {
showResultInUi(coreModel.operation())
}
What is the correct way to implement operation()
to run it on
coreContext with job from current coroutine (to be cancelled when UI context is cancelled) and without custom elements (to prevent activity leaks)
?
Ideally core level should know nothing about custom element’s keys.kristianconk
11/09/2020, 6:22 PMlaunch{
flow1.collect{ ... }
flow2.collect{ ... }
...
}
but only flow1 is executed, if comment flow1 then flow2 is executedkristianconk
11/09/2020, 6:22 PMlaunch{
flow1.collect{ ... }
flow2.collect{ ... }
...
}
but only flow1 is executed, if comment flow1 then flow2 is executednrobi
11/09/2020, 6:25 PMkristianconk
11/09/2020, 6:26 PMwhile(true){
emit(data)
delay(1000)
}
Jason Ostrander
11/09/2020, 6:37 PMnrobi
11/09/2020, 6:39 PMflow.onEach { .... }.launchIn(yourScope)
as @Jason Ostrander suggestedkristianconk
11/09/2020, 6:40 PMgildor
11/09/2020, 11:33 PMSo you need to collect them in different scopesNot different scopes, but different coroutine to collect each, scope can be the same
nrobi
11/10/2020, 4:09 AMcoroutineScope
, rather the scope of the lambda/launch