Why to use Handlers while runOnUiThread does the same?

27,682

Solution 1

Activity.runOnUiThread() is a special case of more generic Handlers. With Handler you can create your own event query within your own thread. Using Handlers instantiated with the default constructor doesn't mean "code will run on UI thread" in general. By default, handlers are bound to the Thread from which they were instantiated from.

To create a Handler that is guaranteed to bind to the UI (main) thread, you should create a Handler object bound to Main Looper like this:

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

Moreover, if you check the implementation of the runOnUiThread() method, it is using Handler to do the things:

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

As you can see from code snippet above, Runnable action will be executed immediately if runOnUiThread() is called from the UI thread. Otherwise, it will post it to the Handler, which will be executed at some point later.

Solution 2

What would be the best way to update my UI? Should I go for Handler or runOnUiThread?

If your Runnable needs to update UI, post it on runOnUiThread.

But it's not always possible to post Runnable on UI Thread.

Think of scenario, where you want need to execute Network/IO operation Or invoke a web service. In this case, you can't post Runnable to UI Thread. It will throw android.os.NetworkOnMainThreadException

These type of Runnable should run on different thread like HandlerThread. After completing your operation, you can post result back to UI Thread by using Handler, which has been associated with UI Thread.

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();
        }
    }
}

Solution 3

Handlers were the old way (API Level 1) of doing stuff, and then AsycTask (API Level 3) were introduced, along with a stronger focus on using runOnUIThread (API Level 1). You should avoid using handlers as much as possible, and prefer the other two depending on your need.

Solution 4

Handler have many work like message passing and frequent UI update if you start A Thread for any running a task .A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue ,, which is very useful in many application like bluetooth chat ,, wifi chat ... and handler has as Method PostDelay and PostAtTime by which you can play around any view to animate and change visibility and so on

You must look in this

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

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

Share:
27,682
Andro Selva
Author by

Andro Selva

Working as mobile developer for past 7 years. Hands on experience with Android native development and Titanium.

Updated on July 08, 2022

Comments

  • Andro Selva
    Andro Selva almost 2 years

    I have come across both Handlers and runOnUiThread concepts. But to me it still seems to be a doubt as on which facts do they differ exactly.

    They both are intended to do UI actions from a background thread. But what are the factors that are to be considered while we choose among the two methods.

    For example consider a Runnable Thread which performs a web service in the background and now I want to update the UI.

    What would be the best way to update my UI? Should I go for Handler or runOnUiThread?

    I still know I could use a AsyncTask and make use of onPostExecute. But I just want to know the difference.