Given ```interface GetSomething { fun invoke(): ...
# compose
s
Given
Copy code
interface GetSomething {
  fun invoke(): Flow<SomeState>
}
If I got a @Composable annotated function which wants to grab this flow and start collecting it. I can either remember it or not
Copy code
class Presenter(private val getSomething: GetSomething) {
@Composable
 fun comp(): UiState {
  val state by getSomething.invoke().collectAsState(...)
  // or
  val state by remember(getSomething) { getSomething.invoke() }.collectAsState(...)
 }
}
And if I understand correctly from testing this out, if I do not remember I definitely trigger invoke on each recomposition, but I also seem to re-start collection on each recomposition too. Since even though
collectAsState
keys the flow itself, those two flows are not the same, do they do not
==
on the key check. Looks like quite an easy pitfall to fall into no? Am I missing something?
z
Sounds right to me. If invoke doesn’t return the same instance every time, it’ll restart collection. So if you can’t guarantee that every impl doesn’t do that you’d need to remember the call.
s
I feel like I need to go back to all of my presenters and triple check I am not messing this up everywhere 😄 Thanks for confirming, what an easy mistake to make though inside molecule or molecule-style presenters!
z
I would hope libraries that create presenters that expose flows cache the flow instance between get calls, to avoid reallocating if nothing else.
a
I think this is related to the lint check that exists for having
Flow
operators outside of
remember
s
Thing is, that interface and impl know nothing about where they're consumed from. The fact that some of them are consumed by a composable presenter is a coincidence. I really wouldn't expect those implementations to cache the flow itself 😶 I think doing the right
remember
is the real solution, as long as I don't forget to do it. The lint check you mention Alex, I didn't get any such hints, is it perhaps some newer compose version, or does it not cover this use case for some reason? I don't recall ever seeing a lint check like that 👀
a
FlowOperatorInvokedInComposition
is the name of the lint rule, but it probably only detects some subset of operations. There’s nothing specifically unique about
Flow<SomeState>
- if you have any
Copy code
interface GetSomething {
    fun invoke(): MyType
}
and it’s important to not query
invoke
more than once, then
remember
is correct to cache it
thank you color 2