Как эффективно управлять несколькими асинхронными задачами в Android

У меня есть сценарий, где мне придется сделать шесть http-вызовов на мой сервер, чтобы получить данные для шести разных элементов. Эти вызовы сервера не могут быть объединены, и они предназначены для этого. Например: если вам нужна информация о цитате для GOOGLE, отправьте запрос на сервер с запросом информации о цитате google. Затем, если вам нужен yahoo, вы инициируете еще один http-вызов и так далее.

ситуация такова:

  1. теперь мой конечный пользователь хочет сравнить 6 различных компаний.
  2. как я уже упоминал, его невозможно избежать для меня, чтобы сделать 6 http-вызовов, для которых я использую 6 асинхронных задач.
  3. когда я получу каждый из ответов асинхронной задачи, я обновлю пользовательский интерфейс новыми данными.
  4. его плохой пользовательский интерфейс, если я обновляю пользовательский интерфейс 6 раз за очень короткий период времени.
  5. его дают мерцающий эффект для моего пользовательского интерфейса, который не требуется.

Мой Вопрос:

  1. как я могу воздержаться от обновления пользовательского интерфейса пока я не получу все 6 асинхронных ответов на задачи?
  2. Я понимаю, что каждая задача не зависит друг от друга. Должен ли я запустить цикл while и ждать, пока не получу все ответы?
  3. есть ли лучший способ сделать это, а не цикл while, потому что, если какой-либо из вызовов не ответит, Я застрял в ожидании навсегда.

примечание: Я думаю, Android 1.6 + выполняет асинхронные задачи параллельно.

Это больше вопрос дизайна и я был бы признателен любая помощь в этом.

спасибо заранее

4 ответов


вы можете сделать объект пула AsyncTask, который позволяет вам подделать "пакетный" http-вызов.

  1. создайте наблюдаемую коллекцию AsyncTasks, я буду ссылаться на эту коллекцию как на ваш пул
  2. Ваша активность создает AsyncTasks (но еще не выполняется) и добавляет их в пул
  3. активность регистрируется как наблюдатель пула
  4. Activity сообщает пулу выполнить, Пул в свою очередь вызывает выполнение каждой из своих задач
  5. когда задачи завершены (как для успеха, так и для неудачи), они хранят данные ответа в пуле, и пул отмечает задачу как "завершенную"
  6. после того, как все задачи помечены как завершенные, пул уведомляет активность прослушивания

общая идея заключается в том, чтобы пул знал, сколько задач и ожидающих выполнения, а также хранил совокупные данные завершенных вызовов. Как только все закончены, сообщите наблюдая деятельность и передайте назад все данные.

вам придется выяснить, как в AsyncTasks рассказать бассейн, что они закончили. Возможно, просто есть реализация AsyncTask, которая принимает Пул в своем конструкторе, чтобы задачи имели ссылку на пул.


есть много способов вы мог бы справиться с этим:

  • другое AsyncTask Это агрегирует ответы от сетевых задач.
  • выполнить sendEmptyMessageDelayed() каждый, скажем, 500 мс до Handler созданные ваши Activity это обновляет данные, поступившие из сетевых задач, и продолжает делать это до тех пор, пока не будут рассмотрены все сетевые результаты.
  • поток, который выполняет агрегацию.

это был я, Я бы, наверное, пошел с Handler. Подводя итог, попросите сетевые задачи хранить данные в каком-либо промежуточном хранилище. Отправляйте отложенные сообщения обработчику и в пределах handleMessage() проверьте наличие данных в промежуточном хранилище и опубликуйте обновленные результаты. Если есть невыполненные результаты, снова опубликуйте отложенное сообщение.


Я нашел это решение более подходящим для моей проблемы. Эта ссылка описывает несколько способов установления этого. 1. ExecutorService 2. ExecutoreService и CountDownLatch

ExecutoreService и CountDownLatch


просто колоть в темноте здесь, но у вас есть:

  • 1X основной поток пользовательского интерфейса
  • 6X фоновые asynchtasks, которые имеют: 6X методы для выполнения в фоновом режиме 6X методы для возврата данных в UI (передний план)

Почему бы не иметь переменную публичной области в потоке пользовательского интерфейса, называемую"finishedTasks", затем тот же метод в каждом из потоков данных возврата 6x, которые:

  • инкременты finishedTasks

  • Если finishedTasks == 6, то запустите 1 public метод для обновления пользовательского интерфейса

затем он обновит пользовательский интерфейс на всех фоновых asychtasks завершения.