#java #android #multithreading #android-service #worker-thread
#java #Android #многопоточность #android-сервис #рабочий поток
Вопрос:
У меня есть служба Android, которая имеет набор операций :
MyService.java
public class MyService extends Service {
public int login() {
//Invokes yet another logic to initiate login and waits for result
//synchronously and returns status code based on result of operation
}
public int logout() {
//Invokes yet another logic to initiate logout and waits for result
//synchronously and returns the status code
}
}
Я вызываю методы, скажем, из клиентской активности, MyClientActivity.java
находящиеся в том же процессе.
Для каждой операции сервис вызывает некоторую логику и синхронно ожидает результата. Когда сервис выполняет всю эту логику, я не хочу, чтобы пользователь выполнял что-либо еще и просто показывал экран загрузки. Итак, в принципе, после того, как я инициировал операцию, я хочу MyClientActivity
синхронно ожидать код состояния. Теперь я знаю, что не могу заблокировать поток пользовательского интерфейса, чтобы избежать ANR.
Как я могу выполнить эту операцию в отдельном потоке, а затем получить результат обратно, чтобы я мог соответствующим образом распространить результат обратно пользователю, изменив пользовательский интерфейс на основе этого результата.
Я довольно новичок в этом и не могу по-настоящему понять концепции. Если кто-нибудь может объяснить вместе с примером, который был бы полезен.
Комментарии:
1. используйте библиотеку обратных вызовов / локальных трансляций / EventBus. Итак, в activity вы просите сервис выполнить запрос, а затем блокируете пользовательский интерфейс (с представлением загрузки). Затем сервис выполняет операции асинхронно, и когда операция завершается — он вызывает некоторый метод Activity (обратный вызов), отправляет локальную широковещательную рассылку, которую вы получаете в Activity, или отправляет событие, которое вы получаете в Activity (библиотека EventBus). Затем в Activity вы разблокируете пользовательский интерфейс и обрабатываете результат
2. Я думал о том, чтобы сделать что-то подобное. Я регистрирую экземпляр обратного вызова из
MyClientActivity
самого себя с помощьюMyService
, и служба может вызвать метод success / failure при этом обратном вызове.MyClientActivity
будет иметь логику для управления пользовательским интерфейсом в соответствующих методах успеха / неудачи реализации обратного вызова. Я сомневаюсь, зачем мне добавлять все это усложнение и дополнительный код, когда мне точно не нужно асинхронное поведение. Я хотел решение без обратных вызовов. В принципеMyClientActivity
следует ожидать результата, но в рабочем потоке вместо основного потока пользовательского интерфейса, чтобы избежать ANR.3. ожидание результата в другом потоке намного сложнее, чем использование обратных вызовов, а также вам в любом случае придется передать что-то, чтобы уведомить поток о завершении операции.
4. Есть ли у вас какая-либо ссылка на пример реализации, в которой клиент ожидает результата в рабочем потоке, а затем уведомляет основной поток? Я просто хочу проанализировать обе модели реализации на предмет гибкости добавления дополнительных операций, если это потребуется в будущем. Я хочу посмотреть, насколько хорошо обе модели поддерживают потенциальные операции с различными требованиями. Также я хочу проанализировать, насколько легко я могу справиться с крайними случаями в обеих моделях, такими как сбой вновь созданного процесса (порожденного
MyService
), гдеMyService
, возможно, никогда не удастся вызвать обратный вызов и т.д.5. Мне особенно нужны были ссылки на реализации с манипулированием потоками, потому что это новая концепция для меня. Исходя из этого, я хочу выбрать подход.
Ответ №1:
В Android существует множество способов выполнять асинхронную работу, как вы описали. Вы можете использовать сервис, загрузчик, если вы используете модифицированную библиотеку для сетевых запросов, в которую встроены асинхронные запросы, поэтому следуйте документации. Также существует RxJava, но его кривая обучения довольно крутая.
Ответ №2:
Я добился этого, используя a HandlerThread
для создания a, Handler
в который я отправляю Runnables
для выполнения фоновых задач.
Для выполнения этих задач основного потока (задач пользовательского интерфейса) Я использую mainLooper
для создания другого, Handler
в который я отправляю сообщения Runnables
для выполнения операций с представлениями.
Приблизительное представление кода :
mBackgroundHandler.post(new Runnable() {
@Override
public void run() {
//Do background operation in synchronous manner as usual.
mMainHandler.post(new Runnable() {
@Override
public void run() {
//Remove loader, update UI
}
});
}
});