Why does refCount behavior require to specify scop...
# coroutines
u
Why does refCount behavior require to specify scope? Scope is implicit via last subscriber unsubscription
a
What scope/context would be used to call
.collect
on the upstream flow? Subscription is about who calls
.collect
, not about who cancels it. Using the scope of the first subscriber wouldn't work since you couldn't support structured concurrency correctly that way. Which dispatcher would you use and why? Questions like this are all answered by providing an explicit scope for shared flows to collect on.
u
Well, its own, global essentially i guess. Same way rxjava does so
Copy code
class FooRepository {
   val foo: Observable<Foo> by lazy {
      fooDao.foo()
         .refCount()
Copy code
}
}
Not sure how can this leak. Last subscriber unsubscribes the upstream. This is what I do all over the app (+ replay), to cache last db emits
a
It's not a question of where it leaks, it's also a question of the rest of the
CoroutineContext
. It's a question of where and how it runs. In effect, with flows there's no such thing as a
subscribe
without a
subscribeOn
and that's just about the dispatcher, ignoring other
CoroutineContext
elements.
If you want something equivalent to rxjava's you can do something like
Copy code
val GlobalRefcountScope = CoroutineScope(NonCancellable + Dispatchers.Unconfined)
and use that, but flow does make you be explicit if that's what you really want.
u
I see. How would I make this more idiomatic? Since my coroutune scope instances live inside stateful objects like viewmodels or managers etc. Repositories are stateless. And until now, in rx they proxied dao observsbles, and applied the replay refcount caching. Now I only see injecting coroutine scope, of which Im not really a fan of, or proxying the repo observable via the manager, and applying caching there, ughh. Or not apply caching, db is relatively fast
a
I would do it wherever you establish your caching policy