AsyncTask, вызванный из Handler, не выполнит doInBackground

Приложение, над которым я работаю, использует фоновый поток для загрузки списка изображений через API, а затем отображает изображения в слайд-шоу.

Существует фоновое задание (в настоящее время AsyncTask), чтобы периодически извлекать новые изображения.

Я не получаю сообщений об ошибках о неправильном Thread и т. Д., Просто второй экземпляр AsyncTasks не будет запускать метод doInBackground.

Вот код из Activity:

private DownloadTask mDownloadTask = null; private Handler mHandler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new Handler() { @Override public void handleMessage(Message msg) { if(mDownloadTask != null) { mDownloadTask.cancel(true); } mDownloadTask = new DownloadTask(); mDownloadTask.execute((Void[]) null); } }; mDownloadTask = new DownloadTask(); mDownloadTask.execute((Void[]) null); } 

DownloadTask выглядит так:

 @Override protected List<String> doInBackground(Void... voids) { // Download list of URLs from server, etc. } @Override protected void onPostExecute(List<String> urls) { mHandler.sendEmptyMessageDelayed(111, 5000); } 

Вызывается обработчик, вызывается onPreExecute (в AsyncTask) и работает начальный запуск DownloadTask (прямо в onCreate ).

Согласно этому вопросу: Android SDK AsyncTask doInBackground не работает (подкласс) , это может быть связано с SDK15.

Спасибо за любые подсказки.


Обновление Поскольку я получил комментарии о том, что обработчик может не быть в потоке пользовательского интерфейса (что является странным, поскольку Thread.currentThread является таким же как в методе onCreate, так и в методе Handlers handleMessage , я пересмотрел метод handleMessage чтобы:

 mHandler = new Handler() { @Override public void handleMessage(Message msg) { runOnUiThread(new Runnable() { @Override public void run() { if(mDownloadTask != null) { mDownloadTask.cancel(true); } mDownloadTask = new DownloadTask(); mDownloadTask.execute((Void[]) null); } }); } }; 

Все равно безуспешно.


Обновить полный класс DownloadTask

 class DownloadTask extends AsyncTask<Void, Void, List<String>> { @Override protected void onPreExecute() { // Cancel the animation. if (mSlideshowAnimation != null) { mSlideshowAnimation.cancel(true); } mImageView1.setVisibility(View.GONE); mImageView2.setVisibility(View.GONE); animate(mProgressBar).alpha(1.0f).setDuration(500).start(); Log.d(TAG, "Download preparation done."); } @Override protected List<String> doInBackground(Void... voids) { Log.d(TAG, "Download"); SharedPreferences s = getSharedPreferences("access", Context.MODE_PRIVATE); String token = s.getString("token", null); Log.d(TAG, "Downloading slideshows."); List<String> urls = new ArrayList<String>(); Slideshow[] slideshows = new Api(SlideshowActivity.this).getSlideshows(token); for (Slideshow slideshow : slideshows) { urls.addAll(slideshow.getAllPhotoUrls()); } Log.d(TAG, "Downloading slideshows: " + slideshows.length); for (String url : urls) { try { url = Api.HOST + url; if (!Cache.fileExists(Cache.getCacheFilenameForUrl(SlideshowActivity.this, url))) { Cache.cacheStream(SlideshowActivity.this, HttpHelper.download(SlideshowActivity.this, url), url); } else { Log.d(TAG, "Cached: " + url); } } catch (IOException e) { Log.e(TAG, "Error while downloading.", e); } } Log.d(TAG, "Downloading slideshows finished."); return urls; } @Override protected void onPostExecute(List<String> urls) { Log.d(TAG, "download successful"); animate(mProgressBar).alpha(0.0f).setDuration(500).start(); mCurrentImageIndex = -1; mImageUrls = urls; mSlideshowAnimation = new SlideshowAnimation(); mSlideshowAnimation.execute((Void[]) null); mHandler.sendEmptyMessageDelayed(111, 5000); } } 

Благодаря полезной дискуссии с Вакасом (спасибо!) Я наконец обнаружил ошибку в моем коде. На самом деле все написанное выше правильно и работает как есть. Проблема с моим делом заключалась в том, что вторая задача заблокировала первую и наоборот.

Возможно, совпадение было найти это сообщение в группах Google: http://groups.google.com/group/android-developers/browse_thread/thread/f0cd114c57ceefe3?tvc=2&q=AsyncTask+in+Android+4.0 . Порекомендуйте, чтобы все участники резьбы внимательно читали эту дискуссию.

AsyncTask переключила модель Threading на последовательный исполнитель (опять же), что несовместимо с моим подходом к созданию двух AsyncTasks.

Наконец, я переключил обработку «Загрузка» на классический Thread и использовал Handler для отправки сообщений для отмены слайд-шоу, если это необходимо. Использование обработчиков sendEmptyMessageDelayed Я просто заново заново sendEmptyMessageDelayed чтобы обновить данные.

Спасибо всем комментариям и ответам.

Handler – это своего рода поток в андроиде, а AsyncTask также работает в разных потоках. Когда вы используете AsyncTask, существует несколько правил.

Для правильного функционирования этого класса необходимо соблюдать несколько правил потоковой передачи:

Экземпляр задачи должен быть создан в потоке пользовательского интерфейса. Execute (Params …) должен быть вызван в потоке пользовательского интерфейса. Не вызывайте onPreExecute (), onPostExecute (Result), doInBackground (Params …), onProgressUpdate (Прогресс …) вручную. Задача может быть выполнена только один раз (исключение будет выбрано при попытке выполнить второе выполнение).

Поэтому ясно сказано, что AsyncTAsk нужно вызывать из потока пользовательского интерфейса .. где, как вы его называете, от Handler, который не является потоком пользовательского интерфейса …

Хорошо попробуйте это тоже

 mHandler = new Handler() { @Override public void handleMessage(Message msg) { runOnUiThread(new Runnable() { @Override public void run() { if(mDownloadTask != null) { mDownloadTask.cancel(true); } if([isCancelled()][1]){ mDownloadTask = new DownloadTask(); mDownloadTask.execute((Void[]) null); } // i assume your task is not getting cancelled before starting it again.. } }); } }; 

А также документация говорит об этом.

Для обработчика используются два основных вида использования:

(1) планировать сообщения и исполняемые файлы, которые должны выполняться как некоторые моменты в будущем; И (2) установить действие, выполняемое в другом потоке, чем ваше собственное.