I used the replaying behavior in rx to cache the l...
# coroutines
u
I used the replaying behavior in rx to cache the latest emit of database, and scope in rx is .. I guess the duration of FooRepository instance lifetime (foo flow instance lifetime)? Well..semantically its not GlobalScope since FooRepository say only lives during user being logged in -- dagger specifies this If I were to have scope as param that would not be nice api. Or maybe use GlobalScope and just leave it up to dagger to scope the FooRepository object, and therefore GC eats this when it goes out of "scope"? Would that be a leak?
g
If I were to have scope as param that would not be nice api.
No, it’s very nice API, it force you to think on lifecycle of this thing, with RxJava you just do not care and may easily leak
semantically its not GlobalScope since FooRepository say only lives during user being logged in
So you answered your own question, provide UserScope, which created on login and cancelled on logout
u
No in rx it doesnt leak, it lives as long as the val owner, i.e. repo lives why would you want to pass different scope, I just want to get db state, and its nice to get memcached one right away
Well okay with autoConnect it could leak yea if disposable not cleared, but not refCount, by design self closing when last subscriber goes away -- maybe you think of when scope cancelation comes sooner then last subscriber goes away? i could see that
My issue is that anybody who sees FooRepo and wants repo stream should be able just to subscribe it, ... and they could be different scopes, so I guess Repo needs its own scope, but I wanted my repos to be stateless .. ok thanks!
g
It cannot be stateless by definition! If you have hot stream (support multiple receivers or caching) it already stateful, but with rx you just doesn't see it without scope
Repo not necessary need own scope, if It uses App/User level scope and it itself app/user scoped
u
Okay I see your point, caching is state, still wouldnt leak the way I use my "object" scopes and refcount but okay I'm trying it in flow with the global scope but it doesnt work 😕
Copy code
object FooRepository {

    val foos: Flow<List<Foo>> = flow { emit(readFoos()) }.shareIn(scope = GlobalScope, started = SharingStarted.Lazily())
}

Activity1 {
	scope.launch {
        FooRepository.foos
            .collect {
                Log.d("Default", "activity1=$it")
            }
	}
}

Activity2 {
	scope.launch {
        FooRepository.foos
            .collect {
                Log.d("Default", "activity2=$it")
            }
	}
}
Activity 1 initiates readFoo and gets result, then via a button I move to Activity2 and that doesnt receive the cached result, nor initiates readFoos -- I must be doing something wrong (If I remove the shareIn and place it in a getter then it works as expected, but obviously without the caching, so the callsites I think are okay) i.e. using the shareIn wrongly
g
It's actual leak or not purely depend on Flow/Observable implementation which you making hot
So of course if you just do flow { emit(1) }.shareIn(GlobalScope) nothing is leaking in reality, but it not always emit(1)
u
Its not a leak if you handle the disposable autoConnect gives you or make sure you unsubscribe all when using refCount but sure, I see your point
g
Right, if you manage it manually
u
which is the same as making sure you dont forget to call scope.cancel basically
g
Consumer can just pass scope in such cases
u
I'd prefer not to but its true my Repo functions are cold/suspending so caller choses its own scope, so why not the database stream aswell to make it symmetrical, but okay I'll think about it, but lets not diverge from my code not working 😄