Подтвердить что ты не робот

Зачем использовать обработчики, в то время как runOnUiThread делает то же самое?

Я столкнулся с обоими обработчиками и runOnUiThread. Но для меня это все еще кажется сомнением, по каким фактам они точно различаются.

Оба они предназначены для выполнения действий пользовательского интерфейса из фонового потока. Но каковы факторы, которые следует учитывать, когда мы выбираем один из двух методов.

Например, рассмотрим Runnable Thread, который выполняет веб-службу в фоновом режиме, и теперь я хочу обновить интерфейс.

Какой был бы лучший способ обновить интерфейс? Должен ли я идти за Handler или runOnUiThread?

Я все еще знаю, что могу использовать AsyncTask и использовать onPostExecute. Но я просто хочу знать разницу.

4b9b3361

Ответ 1

Activity.runOnUiThread() - это особый случай более универсальных обработчиков. С помощью Handler вы можете создать свой собственный запрос о событии в своем собственном потоке. Использование Handlers созданных с помощью конструктора по умолчанию, вообще не означает, что "код будет выполняться в потоке пользовательского интерфейса". По умолчанию обработчики привязаны к Thread из которого они были созданы.

Чтобы создать Handler который гарантированно будет привязан к потоку пользовательского интерфейса (основного), вы должны создать объект Handler связанный с Main Looper следующим образом:

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

Более того, если вы проверите реализацию метода runOnUiThread(), он использует Handler для выполнения следующих действий:

  public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

Как вы можете видеть из фрагмента кода выше, Runnable action будет выполнено немедленно, если runOnUiThread() вызывается из потока пользовательского интерфейса. В противном случае он отправит его в Handler, который будет выполнен в определенный момент позже.

Ответ 2

Обработчик имеет много функций, таких как передача сообщений и частое обновление пользовательского интерфейса, если вы запускаете Thread для любого запуска задачи. Обработчик позволяет отправлять и обрабатывать объекты Message и Runnable, связанные с потоком MessageQueue, который очень полезен во многих приложениях, таких как Bluetooth-чат, wifi chat... и обработчик имеет метод PostDelay и PostAtTime, благодаря которым вы можете играть вокруг любого вида для анимации и изменения видимости и т.д.

Вы должны посмотреть в этом

http://developer.android.com/guide/components/processes-and-threads.html

http://developer.android.com/tools/testing/activity_testing.html

Ответ 3

После ответа HitOdessit.

Вы можете создать такой класс.

public class Global{
    private static Handler mHandler = new Handler(Looper.getMainLooper());
    public static void runOnUiThread(Runnable action){
        mHandler.post(action);
    }
}

И затем назовите его так.

Global.runOnUiThread(new Runnable(){
    //Your code
});

И это можно запустить из любого места (где у вас есть доступ к вашему глобальному классу).

Ответ 4

Обработчики были старыми способами (API Level 1), а затем AsycTask (API Level 3), а также более сильным фокусом на использовании runOnUIThread (API Level 1). Вы должны избегать использования обработчиков в максимально возможной степени и предпочитаете другие два в зависимости от ваших потребностей.

Ответ 5

Какой лучший способ обновить интерфейс? Должен ли я обращаться за обработчиком или runOnUiThread?

Если вашему Runnable необходимо обновить интерфейс, отправьте его на runOnUiThread.

Но не всегда возможно опубликовать Runnable в потоке пользовательского интерфейса.

Подумайте о сценарии, где вам нужно выполнить Операция "Сеть/Ввод" . Или вызвать веб-службу. В этом случае вы не можете отправлять Runnable в тему пользовательского интерфейса. Он будет бросать android.os.NetworkOnMainThreadException

Этот тип Runnable должен работать в разных потоках, например HandlerThread. После завершения операции вы можете отправить результат обратно в поток пользовательского интерфейса, используя Handler, который был связан с потоком пользовательского интерфейса.

public void onClick(View view) {

    // onClick on some UI control, perform Network or IO operation

    /* Create HandlerThread to run Network or IO operations */
    HandlerThread handlerThread = new HandlerThread("NetworkOperation");
    handlerThread.start();

    /* Create a Handler for HandlerThread to post Runnable object */
    Handler requestHandler = new Handler(handlerThread.getLooper());

   /* Create one Handler on UI Thread to process message posted by different thread */

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
    NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
    requestHandler.post(r1);
    requestHandler.post(r2);

}

class NetworkRunnable implements Runnable{
    String url;
    Handler uiHandler;

    public NetworkRunnable(String url,Handler uiHandler){
        this.url = url;
        this.uiHandler=uiHandler;
    }
    public void run(){
        try {
            Log.d("Runnable", "Before IO call");
            URL page = new URL(url);
            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();

            /* Send result back to UI Thread Handler */
            uiHandler.sendMessage(msg);


        } catch (Exception err) {
            err.printStackTrace();
        }
    }
}