Запуск кода в главном потоке из другого потока
237425 просмотра
14 ответа
5546 Репутация автора
В сервисе Android я создал поток (ы) для выполнения некоторых фоновых задач.
У меня есть ситуация, когда поток должен опубликовать определенную задачу в очереди сообщений основного потока, например a Runnable
.
Есть ли способ , чтобы получить Handler
из главного потока и поста Message
/ Runnable
к нему из другого потока?
Спасибо,
Автор: Ahmed Источник Размещён: 20.06.2012 04:07Ответы (14)
4 плюса
14332 Репутация автора
Один метод, который я могу придумать, заключается в следующем:
1) Пусть интерфейс привязывается к сервису.
2) Выставьте метод, подобный приведенному ниже, Binder
который регистрирует ваш Handler
:
public void registerHandler(Handler handler) {
mHandler = handler;
}
3) В потоке пользовательского интерфейса вызовите вышеуказанный метод после привязки к сервису:
mBinder.registerHandler(new Handler());
4) Используйте обработчик в ветке Сервиса, чтобы опубликовать вашу задачу:
mHandler.post(runnable);
Автор: Dheeraj V.S.
Размещён: 20.06.2012 04:41
562 плюса
71848 Репутация автора
ПРИМЕЧАНИЕ. Этот ответ привлек столько внимания, что мне нужно его обновить. Поскольку исходный ответ был опубликован, комментарий от @dzeikei привлек почти столько же внимания, как и оригинальный ответ. Итак, вот 2 возможных решения:
1. Если ваш фоновый поток имеет ссылку на Context
объект:
Убедитесь, что фоновые рабочие потоки имеют доступ к объекту контекста (это может быть контекст приложения или контекст службы). Затем просто сделайте это в фоновом рабочем потоке:
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
2. Если ваш фоновый поток не имеет (или не нужен) Context
объект
(предложено @dzeikei):
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
Автор: David Wasser
Размещён: 20.06.2012 05:49
132 плюса
1879 Репутация автора
Как правильно указывал нижеприведенный комментарий, это не общее решение для сервисов, а только для потоков, запущенных из вашей деятельности (такой поток может быть сервисом, но не все из них). По сложной теме общения между службой и сервисом, пожалуйста, прочитайте весь раздел «Услуги» официального документа - он сложный, поэтому стоит разобраться с основами: http://developer.android.com/guide/components/services.html #Notifications
Метод ниже может работать в самых простых случаях.
Если я вас правильно понимаю, вам нужно, чтобы какой-то код выполнялся в потоке GUI приложения (не могу думать ни о чем другом, называемом «основным» потоком). Для этого есть метод Activity
:
someActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code to run in GUI thread here
}//public void run() {
});
Надеюсь, это то, что вы ищете.
Автор: Alexey Vassiliev Размещён: 20.06.2012 10:1928 плюса
5256 Репутация автора
Если вы запускаете код в потоке, например, задерживаете какое-то действие, вам нужно вызвать его runOnUiThread
из контекста. Например, если ваш код внутри MainActivity
класса, используйте это:
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
myAction();
}
});
Если ваш метод может быть вызван либо из основного (поток пользовательского интерфейса), либо из других потоков, вам нужна проверка, например:
public void myMethod() {
if( Looper.myLooper() == Looper.getMainLooper() ) {
myAction();
}
else {
}
Автор: Alexander Volkov
Размещён: 27.09.2013 09:27
28 плюса
393 Репутация автора
Есть еще один простой способ, если у вас нет доступа к контексту.
1). Создайте обработчик из основного петлителя:
Handler uiHandler = new Handler(Looper.getMainLooper());
2). Реализуем интерфейс Runnable:
Runnable runnable = new Runnable() { // your code here }
3). Отправьте свой Runnable на uiHandler:
uiHandler.post(runnable);
Вот и все ;-) Веселитесь с потоками, но не забудьте синхронизировать их.
Автор: tema_man Размещён: 03.07.2015 07:152 плюса
32019 Репутация автора
HandlerThread
это лучший вариант для нормальных Java-потоков в Android.
- Создайте HandlerThread и запустите его
- Создайте обработчик с помощью Looper из HandlerThread:
requestHandler
post
Runnable
задача поrequestHandler
Связь с UI Thread от HandlerThread
- Создайте метод
Handler
сLooper
для основного потока:responseHandler
иhandleMessage
метод переопределения - Внутри
Runnable
задачи другого Thread (HandlerThread
в данном случае), звонитеsendMessage
поresponseHandler
- Этот
sendMessage
результат вызоваhandleMessage
вresponseHandler
. - Получить атрибуты из
Message
и обработать его, обновить интерфейс
Пример : обновление TextView
с данными, полученными от веб-службы. Поскольку веб-служба должна вызываться в потоке, не связанном с пользовательским интерфейсом, созданным HandlerThread
для работы в сети. Как только вы получите контент от веб-службы, отправьте сообщение обработчику основного потока (поток пользовательского интерфейса), Handler
который обработает сообщение и обновит пользовательский интерфейс.
Образец кода:
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
Handler requestHandler = new Handler(handlerThread.getLooper());
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
txtView.setText((String) msg.obj);
}
};
Runnable myRunnable = new Runnable() {
@Override
public void run() {
try {
Log.d("Runnable", "Before IO call");
URL page = new URL("http://www.your_web_site.com/fetchData.jsp");
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
Полезные статьи:
handlerthreads-и-почему-вы-должны-быть, используя их-в-ваш-Android-приложений
Android-петлителя-обработчик-handlerthread-я
Автор: Ravindra babu Размещён: 09.05.2017 12:401 плюс
810 Репутация автора
Следуйте этому методу. Используя этот способ, вы можете просто обновить пользовательский интерфейс из фонового потока. runOnUiThread работает в основном потоке (UI). Я думаю, что этот фрагмент кода менее сложный и легкий, особенно для начинающих.
AsyncTask.execute(new Runnable() {
@Override
public void run() {
//code you want to run on the background
someCode();
//the code you want to run on main thread
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/
executeAfterOperation();
}
});
}
});
в случае услуги
создать обработчик в oncreate
handler = new Handler();
затем используйте это так
private void runOnUiThread(Runnable runnable) {
handler.post(runnable);
}
Автор: MarGin
Размещён: 19.02.2018 01:42
17 плюса
1339 Репутация автора
Блок сокращенного кода выглядит следующим образом:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// things to do on the main thread
}
});
Это не включает передачу ссылки на действие или ссылку на приложение.
Эквивалент Котлина:
Handler(Looper.getMainLooper()).post(Runnable {
// things to do on the main thread
})
Автор: david m lee
Размещён: 20.02.2018 05:46
2 плюса
469 Репутация автора
Я знаю, что это старый вопрос, но я натолкнулся на одну строчку основного потока, которую я использую и в Kotlin, и в Java. Возможно, это не лучшее решение для службы, но для вызова чего-то, что изменит UI внутри фрагмента, это чрезвычайно просто и очевидно.
Java (8):
getActivity().runOnUiThread(()->{
//your main thread code
});
Котлин:
this.runOnUiThread {
//your main thread code
}
Автор: mevdev
Размещён: 14.06.2018 10:05
0 плюса
1 Репутация автора
public void mainWork() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//Add Your Code Here
}
});
}
Это также может работать в классе обслуживания без проблем.
Автор: Revelation A.F Размещён: 23.08.2018 12:240 плюса
1021 Репутация автора
для Kotlin вы можете использовать Anko corountines :
Обновить
doAsync {
...
}
осуждается
async(UI) {
// Code run on UI thread
// Use ref() instead of this@MyActivity
}
Автор: Francis
Размещён: 17.09.2018 08:00
4 плюса
1043 Репутация автора
Самый простой способ, особенно если у вас нет контекста, если вы используете RxAndroid, вы можете сделать:
AndroidSchedulers.mainThread().scheduleDirect {
runCodeHere()
}
Автор: Inn0vative1
Размещён: 30.10.2018 03:54
3 плюса
956 Репутация автора
Более точный код Kotlin с использованием обработчика:
Handler(Looper.getMainLooper()).post {
// your codes here run on main Thread
}
Автор: Hamed Jaliliani
Размещён: 14.01.2019 11:04
0 плюса
16833 Репутация автора
Котлин версии
Когда вы находитесь на деятельности , а затем используйте
runOnUiThread {
//code that runs in main
}
Когда у вас есть контекст активности , mContext тогда используйте
mContext.runOnUiThread {
//code that runs in main
}
Когда вы находитесь в месте, где нет контекста , используйте
Handler(Looper.getMainLooper()).post {
//code that runs in main
}
Автор: Sazzad Hissain Khan
Размещён: 02.07.2019 12:14
Вопросы из категории :
- android Насколько хорошо отражает эмулятор Android Phone?
- android Как сохранить состояние активности Android с помощью сохранения состояния экземпляра?
- android Android: доступ к дочерним представлениям из ListView
- android Как вызвать SOAP веб-сервис на Android
- android Как вы форматируете дату и время в Android?
- multithreading Что такое состояние гонки?
- multithreading Что такое тупик?
- multithreading Что такое мьютекс?
- multithreading Как начать потоки в plain C?
- multithreading Потокобезопасный foreach перечисление списков
- kotlin Пример диспетчера аварий
- kotlin foreach в котлине
- kotlin Запуск кода в главном потоке из другого потока
- kotlin Как запустить класс Kotlin из командной строки?
- kotlin Котлин: как передать функцию в качестве параметра другой?
- android-handler Обработчик против AsyncTask против потока
- android-handler How to communicate back from a bound service with a Handler?
- android-handler Этот класс обработчика должен быть статическим или может возникнуть утечка: IncomingHandler
- android-handler Реализация обработчиков основным способом