This way of observing a SharedFlow (repeat=0) seem...
# compose
m
This way of observing a SharedFlow (repeat=0) seems to work but it looks suspicious, especially because of
LaunchedEffect(true)
. There's probably some other
Effect
that I should use, right?
Copy code
val pagerState = rememberPagerState(pageCount = pages.size)

LaunchedEffect(true) {
    //SharedFlow 
    pageChangeFlow.collect { 
        pagerState.animateScrollToPage(it) 
    }
}

HorizontalPager(state = pagerState)
d
I personally like
LaunchedEffect(Unit)
tbh.
👍 1
I think that's the effect you want anyway.
🙏 1
i
Seems like you'd want
LaunchedEffect(pagerChangeFlow)
?
👌🏼 1
c
Yep, what Ian said 👆, or
LaunchedEffect(pagerState)
is what I tend to use
d
Or
snapshotFlow { pagerChangeFlow }.flattenConcat()
if you want to be super extra about it.
m
https://google.github.io/accompanist/pager/#reacting-to-page-changes
Buty my code is not indented to find out when page change happens, Instead I want to change page whenever my sharedFlow fires appropriate event.
c
Ah, well it’s a similar pattern. Use the subject as the key for the launch.
There’s no need to
snapshotFlow
the
pagerChangeFlow
, it’s not a stateful property. In fact, it uses
snapshotFlow
underneath
d
If it's not stateful then why use it as an effect key?
m
Do I understand correctly, that the job that contains
pageChangeFlow.collect
will then be tied to the
pagerState
value changes. so whenever the page changes (e.g. user flings manually), it will cancel and relaunch the coroutine? Isn't that wasteful?
i
What
LaunchedEffect(pagerChangeFlow)
means is that if the
pagerChangeFlow
object is replaced with a new object, the previous code block is cancelled and a new code block associated with the new flow is started. Using
true
or
null
would mean that they'd both run
That's why
LaunchedEffect
should always take a key - in just about every case, your
LaunchEffect
is operating on something - that something (or somethings) should be the key
m
Okay, I was referring to
LaunchedEffect(*pagerState*)
which Chris suggested. which is external to the LaunchedEffect.
LaunchedEffect(*pagerChangeFlow*)
is clearer, But just to be sure I understand - in this case, since pagerChangeFlow is an immutable field of viewmodel, it will never be replaced, so technically the difference between that and true/null/Unit is purely semantic?
i
I think Chris was specifically talking about Accompanist's Pager library, of which there's also a variable called
pagerState
, of which a
pageChanges
flow is part of. I suspect this is in fact, your own custom thing, rather than that?
c
Ahhh yes 😂
m
it's the Accompanist HozirontalPager 🙂. oh wait, I get what you meant. Yes,
pageChangeFlow
is my own 😄
i
For truly immutable, effectively singletons, you are correct that using
Unit
as your key does not make any practical difference, but I'd certainly strongly suggest getting into the habit. You never know when the immutable Flow of today instead needs to be wrapped in a remember ala https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda#27a9
💯 1
2
Sometimes best not to assume anything 🙂
👍 1
m
Thank you guys, you are awesome!
👍 1