Доступ к обработчику потоков пользовательского интерфейса из службы - PullRequest
86 голосов
/ 16 июня 2011

Я пробую кое-что новое на Android, для которого мне нужен доступ к обработчику потока пользовательского интерфейса.

Я знаю следующее:

  1. У потока пользовательского интерфейса есть свойобработчик и петлитель
  2. Любое сообщение будет помещено в очередь сообщений потока пользовательского интерфейса
  3. Петлитель получает событие и передает его обработчику
  4. Обработчик обрабатываетсообщение и отправляет событие specfic в пользовательский интерфейс

Я хочу иметь свой сервис, который должен получить обработчик потока пользовательского интерфейса и поместить сообщение в этот обработчик.Так что это сообщение будет обработано и будет выдано пользовательскому интерфейсу.Здесь служба будет нормальной службой, которая будет запущена некоторым приложением.

Я хотел бы знать, возможно ли это.Если да, то предложите несколько фрагментов кода, чтобы я мог их попробовать.

С уважением, Гириш

Ответы [ 7 ]

172 голосов
/ 09 июля 2011

Этот фрагмент кода создает обработчик, связанный с основным потоком (UI):

Handler handler = new Handler(Looper.getMainLooper());

Затем вы можете опубликовать материал для выполнения в основной ветке (UI) следующим образом:

handler.post(runnable_to_call_from_main_thread);

Если сам обработчик создается из основного потока (UI), для краткости аргумент можно опустить:

Handler handler = new Handler();

Руководство разработчика Android о процессах и потоках содержит больше информации.

28 голосов
/ 16 июня 2011

Создайте объект Messenger, прикрепленный к вашему Handler, и передайте его Messenger в Service (например, дополнительно Intent для startService()). Service может затем отправить Message на Handler через Messenger. Вот пример приложения , демонстрирующий это.

4 голосов
/ 28 сентября 2013

В настоящее время я предпочитаю использовать библиотеку шины событий, такую ​​как Otto , для решения этой проблемы.Просто подпишитесь на нужные компоненты (действие):

protected void onResume() {
    super.onResume();
    bus.register(this);
}

Затем предоставьте метод обратного вызова:

public void onTimeLeftEvent(TimeLeftEvent ev) {
    // process event..
}

и затем, когда ваша служба выполнит такой оператор:

bus.post(new TimeLeftEvent(340));

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

2 голосов
/ 21 марта 2014

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

Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");

Затем создайте внутренний класс BroadcastReceiver as,

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    /** Receives the broadcast that has been fired */
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction()=="YOUR_INTENT_FILTER"){
           //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
           String receivedValue=intent.getStringExtra("KEY");
        }
    }
};

Теперь зарегистрируйте приемник вещания в onResume () как,

registerReceiver(broadcastReceiver, intentFilter);

И, наконец, отмените регистрацию BroadcastReceiver в onDestroy () как,

unregisterReceiver(broadcastReceiver);

Теперь самая важная часть ... Вам нужно запустить трансляцию из любой точки, где вам нужно отправить значения ..... так же, как,

Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);

.... ура:)

0 голосов
/ 06 марта 2019

Я предлагаю попробовать следующий код:

    new Handler(Looper.getMainLooper()).post(() -> {

        //UI THREAD CODE HERE



    });
0 голосов
/ 26 октября 2018

В kotlin вот как вы можете это сделать

Допустим, вы хотите показать тостовое сообщение от службы

val handler = Handler(Looper.getMainLooper())
handler.post {
   Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}
0 голосов
/ 28 августа 2017

Решение:

  1. Создание обработчика с Looper из основного потока: requestHandler
  2. Создание Handler с Looper из основного потока: responseHandler и переопределение handleMessage метод
  3. публикация задачи Runnable по запросу requestHandler
  4. внутри задачи Runnable, вызовите sendMessage для responseHandler
  5. Это sendMessage результат вызова handleMessage в responseHandler.
  6. Получение атрибутов из Message и их обработка, обновление пользовательского интерфейса

Пример кода:

    /* Handler from UI Thread to send request */

    Handler requestHandler = new Handler(Looper.getMainLooper());

     /* Handler from UI Thread to process messages */

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {

            /* Processing handleMessage */

            Toast.makeText(MainActivity.this,
                    "Runnable completed with result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    for ( int i=0; i<10; i++) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                   /* Send an Event to UI Thread through message. 
                      Add business logic and prepare message by 
                      replacing example code */

                    String text = "" + (++rId);
                    Message msg = new Message();

                    msg.obj = text.toString();
                    responseHandler.sendMessage(msg);
                    System.out.println(text.toString());

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        requestHandler.post(myRunnable);
    }
...