Поехали...
Особенность заключается в работе метода
cancel().Если обратить внимание, то видно, что данный метод возвращает значение типа
boolean и возможна такая ситуация, при которой данный метод может вернуть false. После такого «провального» вызова метода cancel(), метод isCancelled() также будет возвращать false.Поэтому, если в вашем проекте есть нечто похожее на следующий код, то как минимум, он не всегда может работать так, как вы этого ожидаете.
private class Task extends AsyncTask<Object, Object, Object> { ... protected void onPostExecute(Object result) { if (!isCancelled()) { //do something interesting } } ... }
Причины
Предположим, что AsyncTask завершает свою работу, выходит из метода
doInBackground() и «постит» вызов метода onPostExecute() в главную очередь событий.Так же допустим, что именно в этот момент пользователь выполняет некоторые действия, результатом которых становиться вызов у AsyncTask метода
cancel().В данном случае, метод
onPostExecute() еще не был вызван, но отменить выполнение AsyncTask уже не возможно — метод cancel() вернет false. И, следовательно, метод isCancelled() при последующих вызовах так же будет возвращать false.Происходит это из-за того, что внутреннее состояние AsyncTask ко времени вызова метода
cancel() уже изменилось (так как управление из метода doInBackground() было возращено) и AsyncTask «думает», что уже поставленная задача уже выполнена и отменять нечего.В результате, хотя мы и пытались отменить выполнение AsyncTask, у нас это не получилось. И поэтому, простой проверки
!isCancelled(), как в примере выше не достаточно.Что делать
Если AsyncTask описан в Activity и отменять AsyncTask необходимо только при выходе из Activity, то можно так же проверять возвращаемое значение метода isFinishing.
Но данный способ не особо универсален.
Вариант получше — это написать свой класс (скажем, AbsAsyncTask) и переопределить методы
cancel() и isCancelled(), но в SDK они объявлены как final.Поэтому, в нашем проекте используется класс-обертка, который оборачивает все вызовы методов AsyncTask и при вызове метода
cancel() взводится специальный флаг, который не зависимо от внутреннего состояния AsyncTask позволяет точно узнать вызывался ли метод cancel() или нет.
