Hey everyone. The `ViewModel` now allows use custo...
# android
r
Hey everyone. The
ViewModel
now allows use custom Coroutines Scopes instead of using
viewModelScope
extension
Copy code
@HiltViewModel
class LoginViewModel @Inject constructor(
    private val loginUseCase: LoginUseCase,
    private val viewModelScope: CloseableCoroutineScope,
) : ViewModel(viewModelScope) {
I really like the idea, but I feel you need to be very careful with closing this scope. And so, if one forgets to pass this
CloseableCorotuineScope
to the ViewModel constructor, the scope wont clear itself after ViewModel is destroyed Have anybody solved this issue somehow? My only go-to as of know is building a custom linter, but I’d love to see some other ideas 🙂
🙌 1
1
n
Just use the
viewModelScope
extension if you're not willing to tinker with
ViewModel(CoroutineScope)
?
r
I am willing to tinker, that's why I asked the question 🙂
n
You could use a BaseViewModel and check if the ViewModelScope is a CloseableCoroutineScope... But I guess there's not much more to do
p
Maybe a linter or something
e
You might be missing a key point about coroutine scopes. They are not meant to be auto-closing so this statement doesn’t really make sense
And so, if one forgets to pass this
CloseableCorotuineScope
to the ViewModel constructor, the scope wont clear itself after ViewModel is destroyed
Thing is, a scope delimits the lifecycle of a bunch of work & whoever creates a scope has the responsibility to close that scope when that lifecycle is ended. The fact that you pass a
CloseableCoroutineScope
and it is automatically closed is an implementation detail. Even the
ViewModel
constructor you are referencing takes a list of
Closeables
so it knows nothing about whether its a coroutine scope or not. It only has a simple contract, “if you pass me some closeables, when I am closed, I will auto close those too”.
r
That all makes total sense and I don't think I'm missing anything. Since I want my custom behave same as extension function, I need to pass it to the view model. I completely agree this is my responsibility to do so All i wanted to see by posting this question is any suggestion on how to enforce this particular behavior IMO if you pass something closeable to your View model, i think it most likely needs to be closed after ViewModel is destroyed
👍🏾 1
m
1. Manual scope management: One option is to manually manage the lifecycle of the custom coroutine scope by explicitly clearing it when the ViewModel is destroyed. You can override the
onCleared()
method in your ViewModel and call the
close()
or
cancel()
method on the scope to clean up any active coroutines. This requires careful attention to detail and ensuring that the scope is always cleared correctly. 2. CoroutineScope tied to ViewModel lifecycle: Instead of using a custom coroutine scope, you can tie the lifecycle of your coroutines to the ViewModel's built-in coroutine scope (
viewModelScope
). This scope is automatically cleared when the ViewModel is destroyed. You can achieve this by using the
viewModelScope
directly in your coroutines or by creating child scopes using
viewModelScope.launch
or
viewModelScope.async
. 3. CoroutineScope with AutoDispose: Another option is to use a library like AutoDispose (or similar solutions) that provides automatic disposal of coroutines. These libraries allow you to define a scope for your coroutines that is tied to the lifecycle of the ViewModel. When the ViewModel is destroyed, the library automatically cancels or disposes of any active coroutines within that scope. 4. Custom CoroutineScope wrapper: You can create a custom wrapper around the coroutine scope that handles automatic cleanup. This wrapper can internally manage the lifecycle of the coroutines and ensure they are properly cleared when the ViewModel is destroyed. You can implement this by extending the
CoroutineScope
interface and providing additional methods to handle lifecycle events. Remember, whichever approach you choose, it's essential to thoroughly test and validate the behavior of your ViewModel and coroutines to ensure proper cleanup and prevent any potential memory leaks or unintended behavior.