Как эффективно управлять несколькими асинхронными задачами в Android
У меня есть сценарий, где мне придется сделать шесть http-вызовов на мой сервер, чтобы получить данные для шести разных элементов. Эти вызовы сервера не могут быть объединены, и они предназначены для этого. Например: если вам нужна информация о цитате для GOOGLE, отправьте запрос на сервер с запросом информации о цитате google. Затем, если вам нужен yahoo, вы инициируете еще один http-вызов и так далее.
ситуация такова:
- теперь мой конечный пользователь хочет сравнить 6 различных компаний.
- как я уже упоминал, его невозможно избежать для меня, чтобы сделать 6 http-вызовов, для которых я использую 6 асинхронных задач.
- когда я получу каждый из ответов асинхронной задачи, я обновлю пользовательский интерфейс новыми данными.
- его плохой пользовательский интерфейс, если я обновляю пользовательский интерфейс 6 раз за очень короткий период времени.
- его дают мерцающий эффект для моего пользовательского интерфейса, который не требуется.
Мой Вопрос:
- как я могу воздержаться от обновления пользовательского интерфейса пока я не получу все 6 асинхронных ответов на задачи?
- Я понимаю, что каждая задача не зависит друг от друга. Должен ли я запустить цикл while и ждать, пока не получу все ответы?
- есть ли лучший способ сделать это, а не цикл while, потому что, если какой-либо из вызовов не ответит, Я застрял в ожидании навсегда.
примечание: Я думаю, Android 1.6 + выполняет асинхронные задачи параллельно.
Это больше вопрос дизайна и я был бы признателен любая помощь в этом.
спасибо заранее
4 ответов
вы можете сделать объект пула AsyncTask, который позволяет вам подделать "пакетный" http-вызов.
- создайте наблюдаемую коллекцию AsyncTasks, я буду ссылаться на эту коллекцию как на ваш пул
- Ваша активность создает AsyncTasks (но еще не выполняется) и добавляет их в пул
- активность регистрируется как наблюдатель пула
- Activity сообщает пулу выполнить, Пул в свою очередь вызывает выполнение каждой из своих задач
- когда задачи завершены (как для успеха, так и для неудачи), они хранят данные ответа в пуле, и пул отмечает задачу как "завершенную"
- после того, как все задачи помечены как завершенные, пул уведомляет активность прослушивания
общая идея заключается в том, чтобы пул знал, сколько задач и ожидающих выполнения, а также хранил совокупные данные завершенных вызовов. Как только все закончены, сообщите наблюдая деятельность и передайте назад все данные.
вам придется выяснить, как в AsyncTasks рассказать бассейн, что они закончили. Возможно, просто есть реализация AsyncTask, которая принимает Пул в своем конструкторе, чтобы задачи имели ссылку на пул.
есть много способов вы мог бы справиться с этим:
- другое
AsyncTask
Это агрегирует ответы от сетевых задач. - выполнить
sendEmptyMessageDelayed()
каждый, скажем, 500 мс доHandler
созданные вашиActivity
это обновляет данные, поступившие из сетевых задач, и продолжает делать это до тех пор, пока не будут рассмотрены все сетевые результаты. - поток, который выполняет агрегацию.
это был я, Я бы, наверное, пошел с Handler
. Подводя итог, попросите сетевые задачи хранить данные в каком-либо промежуточном хранилище. Отправляйте отложенные сообщения обработчику и в пределах handleMessage()
проверьте наличие данных в промежуточном хранилище и опубликуйте обновленные результаты. Если есть невыполненные результаты, снова опубликуйте отложенное сообщение.
Я нашел это решение более подходящим для моей проблемы. Эта ссылка описывает несколько способов установления этого. 1. ExecutorService 2. ExecutoreService и CountDownLatch
просто колоть в темноте здесь, но у вас есть:
- 1X основной поток пользовательского интерфейса
- 6X фоновые asynchtasks, которые имеют: 6X методы для выполнения в фоновом режиме 6X методы для возврата данных в UI (передний план)
Почему бы не иметь переменную публичной области в потоке пользовательского интерфейса, называемую"finishedTasks", затем тот же метод в каждом из потоков данных возврата 6x, которые:
инкременты finishedTasks
Если finishedTasks == 6, то запустите 1 public метод для обновления пользовательского интерфейса
затем он обновит пользовательский интерфейс на всех фоновых asychtasks завершения.