Android Handler


Android Handler Tutorial and Examples.

A Handler is a threading class defined in the android.os package through which we can send and process Message and Runnable objects associated with a thread's MessageQueue.

You start by creating a Handler instance. Then that instance gets associated with a single thread as well as that thread's message queue. The Handler you've just created will then get bound to the thread or message queue of the thread that is creating it. Hence it can then deliver messages and runnables to that message queue and execute them as they come out of the message queue.

Uses of Handler

Handler has two main uses

  1. Scehduling of messages and runnables that need to be executed in the future.
  2. Enqueueing actions that need to be performed in the background thread.

Handler and Looper

Handler is a class fundamental to how we do threading in android, at the infrastructure level. It works hand in hand with the Looper. Together they underpin everything that the main thread does—including the invocation of the Activity lifecycle methods.

Looper will take care of dispatching work on its message-loop thread. On the other hand Handler will serve two roles:

  1. First it will provide an interface to submit messages to its Looper queue. 2.Secondly it will implement the callback for processing those messages when they are dispatched by the Looper.

Each Handler gets bound to a single Looper and, by extension, to one thread and its looper MessageQueue.

We said Handler does provide an interface to submit work to Looper threads. Apart from that, Handler also defines the code that process the messages submitted.

For example in the following code, the MyHandler class will override the Handler's handleMessage() method.

This is where we then write our message-handling code:

public class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        // your message handling code here
    }
}

Let's say we have created a thread called MyThread. We can then create our handler inside our MyThread thread over the default constructor Handler().

Hence myHandler will get attached to the current thread's Looper instead of the main thread's Looper:

public class MyThread extends Thread{
    private Handler myHandler;
    @Override
    public void run() {
        Looper.prepare();
        myHandler = new MyHandler();
        Looper.loop();
    }
    public Handler getHandler(){
        return myHandler;
    }
}

Then once started, the Looper thread is going to wait inside loop() method of the Looper class for messages to be added to its queue.

Then another thread can add a message to that queue. It can do that using the submit() method.

When that happens, the waiting thread will dispatch the message to our target MyHandler by invoking the handler's handleMessage() method.

Handler instance/object allows us to be able to send messages to the Handler class from any thread and as a consequence, it is always dispatched to the Looper thread and handled by the correct Handler,

Handler Quick Examples

Let's look at Handler quick examples, snippets and howTos.

1. How to show a splash activity via Handler

Our aim is to show a splash activity via Handler.

Asssume you have this layout as our activity_splash. It has imageview and several textviews.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_splash"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.pchef.cc.personalchef.Splash">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/s_img"
        android:alpha="0.7"
        android:src="@drawable/splash"
        android:scaleType="centerCrop"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerInParent="true">

        <TextView
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:text="Personal Chef"
            android:layout_gravity="center"
            android:gravity="center"
            android:textColor="#fff"
            android:fontFamily="cursive"
            android:textStyle="bold|italic"
            android:layout_marginBottom="50dp"
            android:textSize="60dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textColor="#fff"
            android:textSize="22dp"
            android:fontFamily="sans-serif-condensed"
            android:id="@+id/tv1"
            android:text="Dont know what to cook ?"
            />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tv2"
            android:gravity="center"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:textSize="18dp"
            android:textColor="#fff"

            android:fontFamily="sans-serif-condensed"
            android:text="Our Personal Chef Can help you"
            android:layout_marginTop="14dp" />

    </LinearLayout>

</RelativeLayout>

Then we can come create our SpashActivity. It's deriving from the AppCompatActivity. We are making several imports including the Handler itself as well as Glide, an imageloader library.

import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.Spinner;

import com.bumptech.glide.Glide;

import java.util.concurrent.TimeUnit;

public class Splash extends AppCompatActivity {...}

We'll have an ImageView as our background:

    ImageView background;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        background = (ImageView) findViewById(R.id.s_img);

We'll use glide to load the image into an imageview:

        Glide.with(this)
                .load(R.drawable.splash)
                .into(background);

Finally we come and instantiate our handler:

        final Handler handler = new Handler();

Then invoke the postDelayed() method passing in a Runnable where we implement the run() method.

It is inside the run() method where we do our background stuff. Take note we are also passing the delay in milliseconds.

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //Do something after delay
                finish();
                startActivity(new Intent(Splash.this, Home.class));
            }
        }, 3000);
    }

}
3. How to use a Handler to refresh WebView

In this quick sample we want to use Handler's postDelayed() method refresh a webview. You referesh a webview using the reload() method of the webview. We pass the delay time in milliseconds.

void refreshWebPage(){
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                LightningView webview = getCurrentWebView();
                if (webview != null) {
                    webview.reload();
        }
            }
        }, 200);
    }
4. How to use a Handler to load animation

Android is an animation rich framework. The ability to use animations has been made easier given the presence of a Hnadler. Let's look at a sample snippet that can show us how to load an animation using a Handler. We will pass the view to animate, the animation resource id, the delay time and the Context object. We will use Handler's postDelayed method. There we pass our Runnable annonymous class as well as the delay time.

public static void animationIn(final View view, final int animation, int delayTime, final Context context) {
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        public void run() {
            Animation inAnimation = AnimationUtils.loadAnimation(
                    context.getApplicationContext(), animation);
            view.setAnimation(inAnimation);
            view.setVisibility(View.VISIBLE);
        }
    }, delayTime);
}

That was animation in, well we also have animation out:

 public static void animationOut(final View view, final int animation, int delayTime, final boolean isViewGone, final Context context) {
        view.setVisibility(View.VISIBLE);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            public void run() {
                Animation outAnimation = AnimationUtils.loadAnimation(
                        context.getApplicationContext(), animation);
                view.setAnimation(outAnimation);
                if (isViewGone)
                    view.setVisibility(View.GONE);
                else
                    view.setVisibility(View.INVISIBLE);
            }
        }, delayTime);
    }

Handler post()

Handler has a method called post():

post(Runnable r)

As you can see that method takes a runnable object. The post() method causes the Runnable r to be added to the message queue.

Let's look at several real world examples of this method:

1. Use Handler's post() method to open keyboard

Here's how to use the Handler's post() method to open a Keyboard.

public void openIME(final EditText v) {
    final boolean focus = v.requestFocus();
    if (v.hasFocus()) {
        final Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                InputMethodManager mgr = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
                boolean result = mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
                log.debug("openIME " + focus + " " + result);
            }
        });
    }
}
2. Handler's post() method with Executor

An Executor is an object that executes submitted Runnable tasks.

public DownloadStatusDeliveryImpl(final Handler handler) {
    this.mDownloadStatusPoster = new Executor() {
        public void execute(Runnable command) {
            handler.post(command);
        }
    };
}
3. Full Handler Reusable Utility class
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;

public final class HandlerUtils { 

    private HandlerUtils() { 
    } 

    public static void uiPost(Runnable action) {
        if (action == null) {
            return; 
        } 
        uiHandler().post(action);
    } 

    public static void uiPostDelayed(Runnable action, long delayMillis) {
        if (action == null) {
            return; 
        } 
        uiHandler().postDelayed(action, delayMillis);
    } 

    public static void uiRemoveCallbacks(Runnable action) {
        uiHandler().removeCallbacks(action);
    } 

    public static void threadPost(Runnable action) {
        if (action == null) {
            return; 
        } 
        threadHandler().post(action);
    } 

    public static void threadPostDelayed(Runnable action, long delayMillis) {
        if (action == null) {
            return; 
        } 
        threadHandler().postDelayed(action, delayMillis);
    } 

    public static void threadRemoveCallbacks(Runnable action) {
        threadHandler().removeCallbacks(action);
    } 

    private static Handler uiHandler() {
        return Holder.handler;
    } 

    private interface Holder { 
        Handler handler = new Handler(Looper.getMainLooper());
    } 

    private static Handler sThreadHandler;

    private static synchronized Handler threadHandler() {
        if (sThreadHandler == null) {
            HandlerThread thread = new HandlerThread("HandlerUtils.sThreadHandler");
            thread.start();
            sThreadHandler = new Handler(thread.getLooper());
        } 
        return sThreadHandler;
    } 
} 

4. How to Execure a Specified Runnable on the Main thread

We pass the action to be run on the UI thread.

public final class HandlerUtils {
    private static Handler handler = new Handler(Looper.getMainLooper());

    public static void runOnUiThread(Runnable action) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            action.run();
        }
        else {
            handler.post(action);
        }
    }
}

Full Handler Examples

Let's look at some examples.

Android Handler and ProgressBar Update Tutorial and Examples.

In this tutorial we want to see how to post updates from a background thread to the user interface thread using a Handler.

We click a button and simulate doing heavy work in the background. Meanwhile we are able to update our progressbar as the work continues.

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post