https://kotlinlang.org logo
Docs
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
compose
  • c

    CRamsan

    02/01/2022, 4:26 AM
    Hello everyone, has anyone encountered issues with
    LazyColumn
    and rows of different heights? I have an app where I use
    LazyColumn
    in multiple places for items with different heights and they all work fine except for one screen. In this one screen, trying to scroll UP resets the position and moves the content further down, eventually the user is stuck at the bottom of the list. I have been narrowing down the problem and it seems to repro only when the content has cells of different heights. I tried looking for a bug report bug I could not find anything. I am in the process of trying to narrow down the issue so I can have a demo of it that I can share. But in the meantime I wanted to know if anyone has seen something like this.
    a
    • 2
    • 1
  • k

    K Merle

    02/01/2022, 7:12 AM
    What would be most optimal way to convert hex color to a Compose Color, and to avoid recreation of an object on recomposition? Colors are mainly used inside
    LazyColumn
    . Only thing I could think of is using
    remember
    , but I'd still would have to use
    remember
    inside
    LazyColumn
    .
    a
    a
    • 3
    • 4
  • k

    Kyant

    02/01/2022, 8:32 AM
    How to create a blur effect on specific part of layout? I want to blur the content in the list only behind the bottom bar.
    f
    z
    • 3
    • 6
  • z

    Zoltan Demant

    02/01/2022, 11:27 AM
    Ive been trying to wrap my head around some lingering performance issues Ive been seeing since adopting compose. It seems to happen whenever the state is updated and recompositions happen in a deeeeep hierarchy of composables. Are there any ways I can optimize it such that only parts of the composables are invoked? Ive followed best practices all throughout, but my state is complex, and the composables rendering it are complex as well, yet as simple as Ive been able to make them! More details in thread 🙏🏽🧵
    a
    • 2
    • 3
  • n

    Napa Ram

    02/01/2022, 12:33 PM
    Hey Guys, i am facing issue while changing language from English to Arabic and vice-versa. the issue is screen is blinking and after changing a language as i am selecting a language from dropdown
    f
    g
    • 3
    • 6
  • s

    sindrenm

    02/01/2022, 2:30 PM
    I can't seem to be able to set a proper
    weight(1f)
    on a
    RangeSlider
    . Am I doing something funny, or is this a bug with the component?
    @Preview
    @Composable
    fun RangeSliderTest() {
        var values by remember { mutableStateOf(0f..1f) }
    
        Row(
            modifier = Modifier.background(Color.White).fillMaxWidth().padding(16.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(16.dp),
        ) {
            Text("0")
            RangeSlider(
                modifier = Modifier.weight(1f),
                values = values,
                valueRange = 0f..1f,
                onValueChange = { values = it },
            )
            Text("1")
        }
    }
    k
    y
    • 3
    • 6
  • s

    Stylianos Gakis

    02/01/2022, 4:23 PM
    Use case: When I open a screen, I want a textField to be focused immediately and have the keyboard show. More in thread 🧵
    j
    f
    • 3
    • 7
  • c

    Colton Idle

    02/01/2022, 7:34 PM
    I'm building a simple todo app. There is a single text field when you open the app and it should have the keyboard ready when the app opens. Is this the right way to do it?
    val focusRequester = FocusRequester()
    
      DisposableEffect(Unit) {
          focusRequester.requestFocus()
          onDispose { }
      }
      
    OutlinedTextField(label = {Text("TODO")}, modifier = Modifier.focusRequester(focusRequester),
    Or do I not need a sideEffect?
    f
    s
    z
    • 4
    • 6
  • a

    Adam Powell

    02/01/2022, 8:43 PM
    Nice post, and spot on with the distinction between state and events
    💯 2
    e
    • 2
    • 1
  • b

    brabo-hi

    02/01/2022, 9:30 PM
    Hi all, when using
    AlertDialog
    on
    material3
    , confirmButton and dismissButton don’t show when getting a scrollable list. But it works on
    material2
    t
    • 2
    • 1
  • s

    Simon Stahl

    02/02/2022, 12:24 AM
    Hi. I wonder if there is a way to retrieve a semantic object within a test and assert its values.
    z
    • 2
    • 6
  • j

    julian

    02/02/2022, 3:24 AM
    Does Jetpack Compose offer a way to query the semantic tree? For example, looking for a specific node, maybe marked with a
    testTag
    .
    z
    s
    • 3
    • 6
  • c

    Colton Idle

    02/02/2022, 5:59 AM
    From the android arch docs... trying to understand something
    ...
            LaunchedEffect(userMessage) {
                snackbarHostState.showSnackbar(userMessage.message)
                // Once the message is displayed and dismissed, notify the ViewModel.
                viewModel.userMessageShown(userMessage.id)
            }
    ...
    Is showSnackbar a synchrnous call? i.e. userMessageShown() will be called ONLY after showSnackbar is done/dismissed?
    h
    a
    u
    • 4
    • 8
  • n

    Napa Ram

    02/02/2022, 6:18 AM
    Hi guys Is anyone have sample or demo app to support Language Arabic and English, please share git url Thanks
    👀 1
    z
    • 2
    • 1
  • r

    Ravi

    02/02/2022, 12:30 PM
    Hi, I’ve updated my project to Kotlin 
    1.6.10
    , Compose 
    1.1.0-rc03
     and accompanist 
    0.22.1-rc
     , but I got the exception below, plz let me know how to fix it.
    f
    a
    • 3
    • 9
  • a

    Arpit Shukla

    02/02/2022, 1:36 PM
    Reading the guide to app architecture, I found this note:
    In some apps, you might have seen ViewModel events being exposed to the UI using Kotlin Channels or other reactive streams. These solutions usually require workarounds such as event wrappers in order to guarantee that events are not lost and that they're consumed only once.
    I too (sometimes) use a
    Channel
    to send events from ViewModel to UI as a
    Flow
    which I collect in
    LaunchedEffect
    but I never had to use any
    workarounds such as event wrappers in order to guarantee that events are not lost and that they're consumed only once
    It is automatically taken care of while using channels. What exactly did the author mean here?
    a
    h
    +3
    • 6
    • 13
  • m

    mattinger

    02/02/2022, 2:59 PM
    Has anyone had issues testing a BasicTextField with a custom text style? It seems to cause issues. After i match the text field and call
    performTextInput
    I can no longer match any other elements on the tree. If i use a style from MaterialTheme like body2 it’s fine, but anything else, I get this error:
    offset(6) should be less than line limit(0)
    java.lang.IndexOutOfBoundsException: offset(6) should be less than line limit(0)
    	at android.text.TextLine.measure(TextLine.java:353)
    	at android.text.Layout.getHorizontal(Layout.java:1213)
    	at android.text.Layout.getHorizontal(Layout.java:1190)
    	at android.text.Layout.getPrimaryHorizontal(Layout.java:1160)
    Code is in thread
    b
    c
    • 3
    • 9
  • j

    Junaid

    02/02/2022, 3:37 PM
    neumorphic button with jetpack compose 1.1 Box { Box.blur.light, Box.blur.dark, content } that's it
    ❤️ 6
    :jetpack-compose: 2
    f
    d
    • 3
    • 9
  • k

    kelvinharron

    02/02/2022, 3:49 PM
    Hey folks, I’d like to follow up this post I found in search with a question: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1637659659341600 This is most related to the issue I’m having where I can’t see previews of compose objects in XML (see attached image). We’re integrated compose into our databinding layouts and we aren’t able to get any previews. Given how
    <androidx.compose.ui.platform.ComposeView
    works, and points to something like:
    binding.payButtonLayout.composeButton.apply {
        setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
        setContent {
            MaterialTheme {
                Button(onClick = {}) {
                    Text("My button")
                }
            }
        }
    }
    I’ve tried using the
    tools:composableName="androidx.compose.material.ButtonKt"
    ,
    <androidx.compose.ui.tooling.ComposeViewAdapter
    and even making my own view by inheriting from
    AbstractComposeView
    but still no preview. Would I be correct in saying that this just isn’t possible to do? Thanks in advance!
    d
    • 2
    • 1
  • s

    Stephen Vinouze

    02/02/2022, 3:55 PM
    Hello ✋, I wanted to get your opinion on this small piece of code. I have a
    LandingViewModel
    exposing a
    LandingViewState
    data class LandingViewState(
        val firstPlayerName: String = "",
        val secondPlayerName: String = "",
        val canPlay: Boolean = false,
    )
    I would like the last attribute to be derived from name arguments while only exposing the
    viewState
    – you can see that as a reducer. I haven't been able to find a better pattern than this
    @HiltViewModel
    class LandingViewModel @Inject constructor() : ViewModel() {
    
        val viewState: LandingViewState by derivedStateOf {
            LandingViewState(
                firstPlayerName, secondPlayerName, firstPlayerName.isNotEmpty() && secondPlayerName.isNotEmpty()
            )
        }
        var firstPlayerName: String by mutableStateOf("")
        var secondPlayerName: String by mutableStateOf("")
    
    }
    So I've made the
    viewState
    as a derived state and exposed the other attributes. Ideally, I'd only expose the
    viewState
    as a state and transform the
    canPlay
    on the fly as I'd have done with a reducer. But I can't figure out how to do it with compose
    mutableStateOf
    m
    • 2
    • 4
  • l

    Lukasz Kalnik

    02/02/2022, 4:49 PM
    Is it possible to set in a
    MaterialTheme
    a separate
    typography
    for a
    TextButton
    ? Currently there is only
    typography.button
    . But in our design the regular
    Button
    uses a different text color than a
    TextButton
    .
    j
    c
    • 3
    • 23
  • j

    Joseph Hawkes-Cates

    02/02/2022, 4:57 PM
    This seems like a basic question, but I’m not finding an answer by searching or googling. My starter compose project did not include the compose-compiler dependency and I don’t see it in my dependency tree either. The description of this on developer.android.com says “Transform @Composable functions and enable optimizations with a Kotlin compiler plugin.” What are the main features that dependency adds?
    l
    • 2
    • 2
  • m

    myanmarking

    02/02/2022, 5:43 PM
    I want to create a modifier that will offset the content in the x axis by a specific amount, and then draw a background filling that space. What is the best way of accomplish that ?
    • 1
    • 2
  • a

    allan.conda

    02/02/2022, 6:32 PM
    I’m trying to update Compose to the latest versions, but I’m getting
    Backend Internal error: Exception during IR lowering
    Caused by: java.lang.IllegalStateException: couldn't find inline method Landroidx/compose/runtime/EffectsKt;.rememberCoroutineScope$default
    How can I go about fixing this issue? I can’t find a solution from searching here.
    k
    g
    • 3
    • 13
  • m

    Matti MK

    02/02/2022, 8:46 PM
    I’m wondering if I’m doing something wrong when collecting
    StateFlow
    from Compose, the issue is that the state always “restarts” from initial state when switching between screens on bottom nav. This is an issue when the VM has something different than the initial state, as for some reason the Compose local state always restarts from intial state, before getting the updated state from the VM. On the VM side my flow looks as follows:
    public val viewState: StateFlow<ScreenState> = _internalState.stateIn(
            clientScope,
            SharingStarted.WhileSubscribed(),
            ScreenState(showLoading = true)
        )
    And on my Compose screen collection looks like so:
    fun Screen(
        viewModel: ViewModel = getViewModel(),
    ) {
        val lifecycleOwner = LocalLifecycleOwner.current
    
        val viewStateFlow = remember(viewModel.viewState, lifecycleOwner) {
            viewModel.viewState.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
        }
        val viewState by viewStateFlow.collectAsState(ViewModel.ScreenState(showLoading = true))
    
        Logger.i { "VM state ${viewModel.viewState.value}" } // 1
        Logger.i { " Screen local state is ${viewState}" } // 2
    a
    s
    • 3
    • 12
  • j

    james

    02/02/2022, 9:02 PM
    can anyone advise why my LaunchedEffect code block keeps triggering when coming back to my Composable, despite the key not changing? so my screen is composed, user navigates deeper, then comes back to that first screen using
    navigateUp()
    .. at this point the LaunchedEffect block is triggered again. am I misunderstanding it? code in thread ➡️
    ➕ 1
    i
    • 2
    • 11
  • b

    Bryan Herbst

    02/02/2022, 9:45 PM
    I’m struggling with accessibility behavior for buttons in my app. None of my Compose buttons are reading “Button” with the text in TalkBack. I can’t reproduce this in a different app, it seems to just be my app (currently on 1.0.5). A few interesting things I’ve discovered trying to track this down: • When printing the node tree from TalkBack, the buttons show up as
    Button:invisible
    , which I strongly suspect is the core reason this isn’t working. Digging into TalkBack source, this should only happen when
    AccessibilityNodeInfo.isVisibleToUser
    is false. • I set some breakpoints in
    AndroidComposeViewAccessibilityDelegateCompat
    , and as best as I can tell the node info has
    isVisibleToUser
    correctly set to true, and I do see the correct role showing up here for the buttons What are some things that could cause this? I’ve tried replacing my design systems’ buttons with Material buttons, I’ve tried moving the composables out of Fragments and into the Activity, I’ve tried removing all other content in case something else on the screen was confusing TalkBack, all with no success. I’d love to file a bug, but since I can’t reproduce it outside my application I don’t have much more to provide.
    a
    • 2
    • 4
  • a

    Alex C

    02/03/2022, 2:08 AM
    Has anyone tried to implement a ComposeView inside an android.support.v4.view.NestedScrollingParent? How to deal with nested scrollables in this case?
    a
    • 2
    • 1
  • a

    Anand Verma

    02/03/2022, 5:03 AM
    Hi, I’m new into compose. And I’ve been struggling with managing a lot of states for a UI form. Is there any smarter way through which I can create form & manage states smartly.
    c
    m
    • 3
    • 10
  • s

    steelahhh

    02/03/2022, 8:48 AM
    Having written loads of `LaunchedEffect`s for collecting flows (that are not state, and no way to avoid them for now 🙃), I'm now wondering if there is any difference between one
    LaunchedEffect
    for all of them vs one
    LaunchedEffect
    per flow See 🧵 for example
    b
    z
    +4
    • 7
    • 16
Powered by Linen
Title
s

steelahhh

02/03/2022, 8:48 AM
Having written loads of `LaunchedEffect`s for collecting flows (that are not state, and no way to avoid them for now 🙃), I'm now wondering if there is any difference between one
LaunchedEffect
for all of them vs one
LaunchedEffect
per flow See 🧵 for example
LaunchedEffect(Unit) {
        someflow
        	.onEach { /* ... */ }
            .launchIn(this)
            
            
        someflow1
        	.onEach { /* ... */ }
            .launchIn(this)
            
            
        someflow2
        	.onEach { /* ... */ }
            .launchIn(this)
    }
    
    // OR
    LaunchedEffect(Unit) {
        someflow
        	.onEach { /* ... */ }
            .launchIn(this)
    }
    
    LaunchedEffect(Unit) {
        someflow1
        	.onEach { /* ... */ }
            .launchIn(this)
    }
    
    LaunchedEffect(Unit) {
        someflow2
        	.onEach { /* ... */ }
            .launchIn(this)
    }
b

Big Chungus

02/03/2022, 8:54 AM
Can't you just use myFlow.asState()
s

steelahhh

02/03/2022, 8:56 AM
These flows are not state, but analytics, navigation and some project specific trickery. So nope, I unfortunately cannot do that
z

Zoltan Demant

02/03/2022, 9:12 AM
I think that would just result in the first flow being collected, suspending the coroutine until cancelled (or effectively, forever). Ive seen some peeps call
launch{}
inside the LaunchedEffect to collect multiple flows though, but I dont know how that differs from just using multiple LaunchedEffects!
m

myanmarking

02/03/2022, 9:18 AM
no. launchIn doesn’t suspend so its fine in that regard. idk about best practice tho
👍🏽 1
👍 1
z

Zoltan Demant

02/03/2022, 9:30 AM
Youre right @myanmarking! Effectively its the same thing, but shorter, than
launch { flow.collect }
👍🏽
m

myanmarking

02/03/2022, 9:30 AM
exactly
i started to use launchIn instead of launch+collect in the viewModel because too many times i ‘missed’ the fact that collect will just suspend 😛 so the code next to that call was not executing. It’s stupid, but happens :p
👍 1
s

Stylianos Gakis

02/03/2022, 12:27 PM
Since I saw
launchedIn
mentioned here, I feel the obligation to link this https://www.billjings.com/posts/title/avoid-launchin/?up=technical . I really liked it as an idea and I think that it has helped me make some of my code nicer. I still use it myself too, but a tiny bit less.
💯 1
👍🏽 1
a

Arjun Achatz

02/03/2022, 1:33 PM
I think it's best to break them up, as mentioned here, a less experienced developer might accidentally call collect instead of launchIn, and then your whole chain of effects are potentially lost
m

myanmarking

02/03/2022, 2:18 PM
@Stylianos Gakis yes i read that post a while ago. I disagree with the autor. There are plenty of usecases for launchIn
s

Stylianos Gakis

02/03/2022, 2:24 PM
Absolutely. Whatever works for you and your team. I just thought it’d be a perfect opportunity to introduce this point of view as well as I think it’s interesting, and I personally really like the idea of using coroutines for more than just normal RX-like async callback work. Or at least knowing that I have the possibility to do so 😉
a

Adam Powell

02/03/2022, 2:55 PM
More LaunchedEffects have slightly more overhead, otherwise these approaches are mechanically equivalent
Bill's blog post is an excellent read and a good way to calibrate your thinking when it comes to flows. The OP shows one of the exceptions that prove the rule, since it's just being used as a shortcut for launch { foo.collect... }
But it's highly likely that as code like the OP's grows over time, you will want to refactor and extract pieces of it, and launch+collect will make that a more obvious transformation than onEach+launchIn.
☝️🏽 1
☝️ 1
If you've trained yourself to read onEach+launchIn as equivalent to launch+collect then this might not be an issue for you, but as Bill pointed out, if you haven't and you think in callbacks rather than in suspend, you'll probably find a worse way to do that refactoring
View count: 3