I may be barking up the wrong tree here, but I'm t...
# multiplatform
h
I may be barking up the wrong tree here, but I'm trying to create/destroy coroutine scopes when my viewmodels are instantiated/destroyed. I know
Finalize
wasn't the greatest solution when it came to Java's GC, but with KMM supporting more than just Android, is there a better way to destroy a coroutine scope along with its viewmodel?
c
Are you considering the VM scope to simply be when it is no longer referenced anywhere and able to be GCd? That’s a very brittle way to handle the VM scopes; you will almost certainly en up with leaks as object references can sometimes be very subtle (captured implicitly in a lambda, for example). Rather than having the lifecycle of the VM control the CoroutineScope, have you considered the opposite, and letting the lifetime of the coroutineScope dictate the scope of the VM? This is what I do in my state management library, Ballast, and during initial development I tried having an explicit
vm.close()
function, but found it very hard to sync that with the coroutineScope properly. But once I switched it around so that the scope controls the VM, then you only have 1 lifetime to worry about, the VM cleans itself up, and the whole thing becomes more predicable and easier to manage.
For example:
h
Thanks for such a detailed answer! Before migrating to KMM, I was using the usual Android approach with ViewModelScope. With KMM not having Lifecycles outside of libraries, I was trying to think of a simple way I could couple the two so I could dispose of any running threads once a screen was popped from a stack. I'd never have thought of reversing it so the VM was dependent on a Coroutine's lifetime. Have you found any difficulties or weirdness implementing it?
c
Nope, no difficulties with this approach at all, and I’ve been using this pattern in production apps for over a year. The only thing to keep in mind is that anything the VM does should be launched into the VM scope to make sure all work gets cancelled when the scope gets closed, and so you can’t do any processing after that.
h
Alright, thank you for your help!
Also, at what point is
start()
called? I'm assuming in
AppScreen()
?
c
As early as you can when creating the ViewModel. For example, in Ballast, it’s called internally from the base class’s constructor, so you don’t really need to manage the VM’s lifetime at all. You pass in a coroutine scope, the VM starts itself up, and then when the coroutine scope gets cancelled the Vm shuts itself down