Feature of the AsyncTask class
In this article, we will talk about one feature of the AsyncTask class , which at first glance is not striking, but can lead to undesirable consequences.
The peculiarity lies in the method
If you pay attention, it is clear that this method returns a type value
Therefore, if your project has something similar to the following code, then at least it may not always work as you expect it to.
Assume that AsyncTask finishes its work, exits the method
Let's also assume that at this very moment the user performs some actions, the result of which is a call to the AsyncTask method
In this case, the method
This is due to the fact that the internal state of AsyncTask
As a result, although we tried to cancel AsyncTask, we did not succeed. And therefore, a simple check
If AsyncTask is described in Activity and AsyncTask needs to be canceled only when you exit Activity, then you can also check the return value of the isFinishing method .
But this method is not particularly universal.
A better option is to write your class (say, AbsAsyncTask) and override the
Therefore, our project uses a wrapper class that wraps all calls to AsyncTask methods and when calling a method, a
Go...
The peculiarity lies in the method
cancel()
. If you pay attention, it is clear that this method returns a type value
boolean
and a situation is possible in which this method can return false
. After such a “failed” method call cancel()
, the method isCancelled()
will also return false
. Therefore, if your project has something similar to the following code, then at least it may not always work as you expect it to.
private class Task extends AsyncTask
Causes
Assume that AsyncTask finishes its work, exits the method
doInBackground()
and "posts" the method call onPostExecute()
to the main event queue. Let's also assume that at this very moment the user performs some actions, the result of which is a call to the AsyncTask method
cancel()
. In this case, the method
onPostExecute()
has not yet been called, but it is no longer possible to cancel AsyncTask execution - the method cancel()
will return false
. And, therefore, the method isCancelled()
will also return on subsequent calls false
. This is due to the fact that the internal state of AsyncTask
cancel()
has already changed by the time the method is called (since the control from the methoddoInBackground()
was returned) and AsyncTask "thinks" that the task already set has already been completed and there is nothing to cancel. As a result, although we tried to cancel AsyncTask, we did not succeed. And therefore, a simple check
!isCancelled()
, as in the example above, is not enough.What to do
If AsyncTask is described in Activity and AsyncTask needs to be canceled only when you exit Activity, then you can also check the return value of the isFinishing method .
But this method is not particularly universal.
A better option is to write your class (say, AbsAsyncTask) and override the
cancel()
and methods isCancelled()
, but they are declared final in the SDK. Therefore, our project uses a wrapper class that wraps all calls to AsyncTask methods and when calling a method, a
cancel()
special flag is raised that, regardless of the internal state of AsyncTask, allows you to know exactly whether the method was called cancel()
or not.