В сервисе Android я создал поток (ы) для выполнения некоторых фоновых задач.
У меня есть ситуация, когда поток должен опубликовать определенную задачу в очереди сообщений основного потока, например a Runnable
.
Есть ли способ , чтобы получить Handler
из главного потока и поста Message
/ Runnable
к нему из другого потока?
Спасибо,
Ответы:
ПРИМЕЧАНИЕ. Этот ответ привлек столько внимания, что мне нужно его обновить. Поскольку исходный ответ был опубликован, комментарий от @dzeikei привлек почти столько же внимания, как и оригинальный ответ. Итак, вот 2 возможных решения:
1. Если ваш фоновый поток имеет ссылку на
Context
объект:Убедитесь, что фоновые рабочие потоки имеют доступ к объекту контекста (это может быть контекст приложения или контекст службы). Затем просто сделайте это в фоновом рабочем потоке:
2. Если ваш фоновый поток не имеет (или не нужен)
Context
объект(предложено @dzeikei):
источник
Handler
(или используетеHandler.Callback
интерфейс), вашhandleMessage()
метод будет вызываться ТОЛЬКО для сообщений, отправленных с использованием вашего обработчика. Основной поток использует другой обработчик для отправки / обработки сообщений, поэтому нет конфликта.Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
Как правильно указывал нижеприведенный комментарий, это не общее решение для сервисов, а только для потоков, запускаемых из вашей деятельности (такой поток может быть сервисом, но не все из них). По сложной теме общения между службой и сервисом, пожалуйста, прочитайте весь раздел «Услуги» официального документа - он сложный, поэтому стоит разобраться с основами: http://developer.android.com/guide/components/services.html #Notifications
Метод ниже может работать в самых простых случаях.
Если я вас правильно понимаю, вам нужно выполнить некоторый код в потоке GUI приложения (не могу думать ни о чем другом, называемом «основным» потоком). Для этого есть метод на
Activity
:Документ: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
Надеюсь, это то, что вы ищете.
источник
Service
. Вы не можете использоватьrunOnUiThread()
вService
. Этот ответ вводит в заблуждение и не затрагивает заданный вопрос.Есть еще один простой способ, если у вас нет доступа к контексту.
1). Создайте обработчик из основного петлителя:
2). Реализуем интерфейс Runnable:
3). Опубликуйте свой Runnable для uiHandler:
Вот и все ;-) Веселитесь с потоками, но не забудьте синхронизировать их.
источник
Если вы запускаете код в потоке, например, задерживаете какое-то действие, вам нужно вызвать его
runOnUiThread
из контекста. Например, если ваш код внутриMainActivity
класса, используйте это:Если ваш метод может быть вызван либо из основного (поток пользовательского интерфейса), либо из других потоков, вам нужна проверка, например:
источник
Service
. Вы не можете использоватьrunOnUiThread()
вService
.Activity
документацию,runOnUiThread()
это методActivity
. Это не методService
, поэтому вы не можете его использовать. Что может быть понятнее этого?Блок сокращенного кода выглядит следующим образом:
Это не включает передачу ссылки на действие или ссылку на приложение.
Эквивалент Котлина:
источник
Котлин версии
Когда вы находитесь на мероприятии , а затем используйте
Когда у вас есть контекст активности , mContext тогда используйте
Когда вы находитесь в месте, где нет контекста , используйте
источник
runOnUiThread(){...}
Самый простой способ, особенно если у вас нет контекста, если вы используете RxAndroid, вы можете сделать:
источник
Более точный код Kotlin с использованием обработчика:
источник
Один метод, который я могу придумать, заключается в следующем:
1) Пусть пользовательский интерфейс привязывается к сервису.
2) Выставьте метод, подобный приведенному ниже,
Binder
который регистрирует вашHandler
:3) В потоке пользовательского интерфейса вызовите вышеуказанный метод после привязки к сервису:
4) Используйте обработчик в ветке Сервиса, чтобы опубликовать вашу задачу:
источник
HandlerThread
это лучший вариант для нормальных Java-потоков в Android.requestHandler
post
Runnable
задача поrequestHandler
Связь с UI Thread от
HandlerThread
Handler
сLooper
для основного потока:responseHandler
и переопределитьhandleMessage
метод методRunnable
задачи другого потока (HandlerThread
в этом случае), вызовsendMessage
поresponseHandler
sendMessage
результат вызоваhandleMessage
вresponseHandler
.Message
и обработать его, обновить интерфейсПример : обновление
TextView
с данными, полученными от веб-службы. Поскольку веб-служба должна вызываться в потоке, не связанном с пользовательским интерфейсом, созданнымHandlerThread
для работы в сети. Как только вы получите контент от веб-службы, отправьте сообщение обработчику основного потока (поток пользовательского интерфейса), и этоHandler
который обработает сообщение и обновит пользовательский интерфейс.Образец кода:
Полезные статьи:
handlerthreads-и-почему-вы-должны-быть, используя их-в-ваш-Android-приложений
Android-петлителя-обработчик-handlerthread-я
источник
Я знаю, что это старый вопрос, но я натолкнулся на одну строчку основного потока, которую я использую и в Kotlin, и в Java. Возможно, это не лучшее решение для службы, но для вызова чего-либо, что изменит UI внутри фрагмента, это чрезвычайно просто и очевидно.
Java (8):
Котлин:
источник
Следуйте этому методу. Используя этот способ, вы можете просто обновить пользовательский интерфейс из фонового потока. runOnUiThread работает в основном потоке (UI). Я думаю, что этот фрагмент кода менее сложный и легкий, особенно для начинающих.
в случае услуги
создать обработчик в oncreate
затем используйте это так
источник
для Kotlin вы можете использовать Anko corountines :
Обновить
Устаревшее
источник
Так что наиболее удобно сделать что-то вроде:
И после:
источник
Это также может работать в классе обслуживания без проблем.
источник
С Kotlin это так же, как внутри любой функции:
источник
Activity
.