Hey guys, With the new viewModelScope, when it ge...
# android
g
Hey guys, With the new viewModelScope, when it gets cancelled, why doesn’t future launch call do anything?
Copy code
viewModelScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) {
            contentLiveData.postValue(getDiscoverContentUseCase.execute())
        }
If I put a breakpoint on launch line I see it’s cancelled.
Copy code
viewModelScope = {CloseableCoroutineScope@5985} 
 coroutineContext = {CombinedContext@5986} "[SupervisorJobImpl{Cancelled}@7ed8dea, Main]"
i
"A failure of a child job that was created using launch can be handled via CoroutineExceptionHandler in the context."
g
Fairly new to this so not sure what that means
i dont see any exceptions or logs indicating something had failed
i
I think you are not really catching it.
g
Are you saying something inside the launch { } is failing?
i
yeah
g
I did something like:
Copy code
viewModelScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) {
            Log.i(TAG, "Inside launch")
         }
And it’s not getting to the Log statement
i
try without (Dispatchers.IO)
g
I am switching between fragments (where one of hte fragment has the viewmodel) and if the fragment is created/destroyed fast the viewmodel enters a cancelled state
ok will try
Same thing:
Copy code
viewModelScope = {CloseableCoroutineScope@5902} 
 coroutineContext = {CombinedContext@5929} "[SupervisorJobImpl{Cancelled}@e3d3400, Main]"
Also tried:
Copy code
val handler = CoroutineExceptionHandler { _, exception ->
            Log.e(TAG, "Error $exception", exception)
        }
        viewModelScope.launch(handler) {
And not getting the log
l
viewModelScope
is belonged to the
ViewModel
so it will cancel the future launch when you switch fragments quickly
g
so once a scope is cancelled there’s no way to restart it?
l
It depends on your ViewModel
g
it’s the same viewmodel instance
the fragment is destroyed and re-created
l
Your ViewModel should belong to the activity???
g
it does
in the fragment it’s
viewModel = ViewModelProviders.of(requireActivity(), viewModelFactory).get(MyViewModel::class.java)
m
Where do you call launch ? You sure you’re calling that function to start it ?
g
The call is made in onviewcreated and it's called since i can reach breakpoint on launch line.
It just never enters the inside of lsuch block since the scope is cancelled as I posted
Isuch =launch
m
hmm, I also use viewModelScope but didn’t encounter this issue so far. Sounds more like a lifecycle issue. ViewModel should be cancelling this scope in
onCleared
method. Overriding and debugging it might reveal the reason
That might be a clue
m
Yes indeed.
cancel
is called in
ViewModel.kt
for
viewModelScope
. Did you hit
onCleared
in debugging ?
g
Yup I did
m
Based on your previous snippets, you’re sharing this viewmodel by using activity lifecycle right ? Didn’t really debug similar situation, but it seems viewModel gets cleared, but not destroyed, and doesn’t re-create the coroutine scope 🤔
g
Yeah the activity hasn't changed
I'm actually making a leanback TV app
And I have one activity and one fragment.. Inside the fragment I have a tab system that changed pages (child fragment manager transactions)
When I change tabs I replace the (child) fragment
So the child fragment rely on view model that gets a cleared event and subsequently the scope is set to cancelled
I might just have to use my own scope and job cancelations on clear or on repetitive load calls
m
Seems like a solution,
cancelChildren
instead of
cancel
in
onCleared
. Wonder what causes VM to clear and cancel it’s scope. Would be nice to update here if you find out !
170 Views