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.

    Go...


    The peculiarity lies in the method cancel().
    If you pay attention, it is clear that this method returns a type value booleanand 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 {
         ...
         protected void onPostExecute(Object result) {
             if (!isCancelled()) {
                 //do something interesting
             }
         }
         ...
    }
    


    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.

    Also popular now: