⬆️ ⬇️

Feature of work of class AsyncTask

In this article, we will talk about one feature of the AsyncTask class, which is not striking at first glance, but can lead to undesirable consequences.



Go...



The peculiarity lies in the work of the cancel() method.

If you pay attention, you can see that this method returns a boolean value and it is possible that this method may return false . After such a “failure” call to the cancel() method, the isCancelled() method 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.



 private class Task extends AsyncTask<Object, Object, Object> { ... protected void onPostExecute(Object result) { if (!isCancelled()) { //do something interesting } } ... } 




The reasons



Suppose that AsyncTask finishes its work, exits the doInBackground() method and “posts” the call to the onPostExecute() method to the main event queue.

Also suppose that at this very moment the user performs some actions, the result of which is to call AsyncTask the cancel() method.

')

In this case, the onPostExecute() method has not yet been called, but it is no longer possible to cancel the AsyncTask execution - the cancel() method will return false . And, therefore, the method isCancelled() on subsequent calls will also return false .



This happens due to the fact that the internal state of AsyncTask has already changed by the time the call to the cancel() method (because the control from the doInBackground() method doInBackground() been returned) and AsyncTask “thinks” that the task has already been completed and there is nothing to cancel.



As a result, although we tried to cancel the execution of 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 it is necessary to cancel AsyncTask only when exiting the 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 isCancelled() methods, but they are declared final in the SDK.

Therefore, in our project a wrapper class is used that wraps all calls to AsyncTask methods and when calling the cancel() method, a special flag is set that regardless of the internal state of AsyncTask, it is possible to know for sure whether the cancel() method was called or not.

Source: https://habr.com/ru/post/116309/



All Articles