AsyncTask inside a ViewModel (advanced answer)
This is to demonstrate how to fit an instance of AsyncTask
running inside a ViewModel
. I wouldn’t be using it in production, but you can use it during a more advanced job interview.
This time the instance of the AsyncTask is created inside a ViewModel
and properly canceled.
This may remind you of the refactoring I did in the article ‘ViewModel and CompositeDisposable’, in which I created an RxJava Disposable
- and properly disposed it - inside a ViewModel
, so that the Disposable
didn’t have to be handled inside an Activity
or a Fragment
.
The previous article
You might not understand the present article unless you have read the previous one in which I discuss why I decided to discuss AsyncTask
in the first place.
The ViewModel
This is the code of the ViewModel
containing an instance of the AsyncTask
:
The Fragment
This is the code creating the observations inside the Fragment
. It also adds a button canceling the AsyncTask
.
Please note that even if the canceling button is not pressed at all, the taks will be also canceled when the ViewModel
is cleared, due to the overridden function onCleared
.
This is the code that builds an instance of the AsyncTaks
:
The AsyncTask
This is the code running in the AsyncTask
, away from the UI thread:
Because I use a repeat()
function that takes a lambda, I have to use the expression return@repeat
to break it. If I was using a for
loop, I would write break
instead.
In the above code I had to use the function runBlocking()
to obtain a scope in which I could run the suspend
function delay()
. In the previous article I demonstrated a failed attempt to do the same with with launch()
. It didn’t work, because launch()
returns immediately, therefore onPostExecute()
would be run before the counting even ends. Here I use runBlocking()
which blocks the current thread until the block it contains is completed. The disadvantage of runBlocking()
and AsyncTask
in general is such that on Android all AsyncTaksk
are executed in one thread, and because this particular AsyncTask
takes about 10 seconds to run, no other AsyncTask
should be executed simultaneously on the device. In the real case, if this code was meant to go to production, I would probably skip using an AsyncTask
and use some other coroutine scope or RxJava instead.
Conclusion
In this article you have learned how to refactor the code from the previous article to allow for canceling the task - both from the UI button, and in reaction to lifecycle events.
In the real job interview I usually try to talk about the AsyncTask
as little as possible, and try to suggest talking about RxJava or coroutines instead, but there you have it. If you want to have a working model of an AsyncTask
that probably doesn’t lead to memory leaks, and properly responds to lifecycle events, you see my proposition.
The code used in the present article is at the time of writing it available in my repository.