I’ve implemented a `(Mutable)CacheFlow` that exten...
# flow
m
I’ve implemented a
(Mutable)CacheFlow
that extends
(Mutable)StateFlow
. The main difference is that it can be recursive (normal MutableStateFlow) or non-recursive. When it’s non-recursive then providing a new value to the
MutableCacheFlow
will not emit it to the same flow, thereby avoiding recursive scenarios. Collectors of the recursive cache behind the non-recursive cache will still receive newly emitted value. That means if we have a
cache
and two non-recursive `MutableCacheFlow`s
flow1
and
flow2
then updates to
flow1
would only be collected by
flow2
and updates to
flow2
would only be collected by
flow1
. This is especially useful when values coming out of the cache are transformed downstream and then committed to the cache again. With a regular
MutableStateFlow
that would cause an endless recursion. https://gist.github.com/fluidsonic/a06419b1c129f3045558c63cbafecca4 Thoughts?
Actually that Flow should be shared as updating the cache can be expensive.
e
It looks like you are trying to build a synchronous data binding framework (like JavaFx ObservableProperties, LiveData, etc). However, Flow is an asynchronous data streaming framework and tricks like this, in practice, would often break in non-trivial ways, causing lots of wasted root-cause-finding hours. They key to the effective usage of Flow is to structure your data flows unidirectionally. With an appropriate application architecture none of that is needed.
💯 2
👍 1
m
Thank you for your feedback. Isn’t it uni-directional because the non-recursive emission downstream doesn’t cause another emission from the same
MutableStateFlow
that’s used upstream? How would would you design that use case instead? 1. read input from cache 2. use latest input to repeatedly emit new values fetched from server 3. commit latest value to cache The upstream cache flow typically emits only one value (
null
or data). It may in rare cases emit another
null
to reset the cache and force new data to be loaded. In even rarer cases another part of the app may cache a newer value it somehow obtained and this flow needs to operate the refetching logic on the new value.