Android – Threads Tutorial – Part 3

Today we’ll learn more about Handlers and Threads and we’ll have an example with a class inheriting Thread, using Messages and Handlers. This is gonna be a long post with lots of information, hopefully not overwhelming.

First take a look at the official documentation on Handler. Things we should remember:

  • They are some kind of special “doors” and background managers for the Threads. They are a way to communicate with/process within a Thread.
  • Each Handler is associated with a single Thread and that Thread’s specific message queue. From the moment of its  creation the Handler is linked with the parent Thread (the one that created it). They deliver messages and runnable objects to that message queue and execute them as they come out of the message queue.

They have two main uses:

  • On the same Thread – schedule messages and runnables to be executed at specific times – used for implementing timeouts or ticks.
  • On another Thread – send data/enqueue actions on another Thread.
  • Messages can contain data and are processed by handleMessage() method. Runnable objects can be enqueued in a Thread’s message queue to be executed.
  • Methods using Message start with “send”, methods for Runnable objects start with “post”.
  • Methods for Messages/Runnables that are processed delayed – postAtTime(), postDelayed(), sendMessageAtTime(), sendMessageDelayed().

Let’s take a look at the following diagrams. We have two Threads, each with a Handler.

Diagram 1

Diagram 1

On the second diagram we can see both Handler uses:

  1. Delayed action on the same Thread – Send msg1 to the local Handler in Thread1 (by example with sendMessageDelayed()) and the Handler will act on Thread1 with the specified delay. This can be used to create a tick or time-out behavior – we’ll take care of this in another post
  2. Action on another Thread (can also be delayed) – Send msg2 to Thread’s2 Handler to determine an action of the Thread2 – we’ll see this in today’s example
Diagram 2

Diagram 2

Example – Class that inherits Thread

This little application shows a text that slides to the left or the right side of the display. If the user touches the left side of the screen the text starts moving to left and vice versa. When the user touches the bottom side of the screen the text stops moving.

Application view

Application view

Here is a simple diagram of the two classes we use in order to link our application with what we’ve discussed above.

Diagram 3

Diagram 3

We have a class that inherits Thread defined in a separate file. This is a good practice when the Threads behavior is complex and expected to change over time. We’ll see a way to interrupt the Thread and also sending messages with data between two Threads. Also we’ll see how to find the location where the user touches the screen, simple logging and ternary operations. I’ll keep it as simple as possible and don’t manage different screen sizes and other settings issues.

As usual, let’s see first the basic form of the code to be understood:

// File MainClassName.java
public class MainClass [extends Activity] {

    // our special Thread instance var
    private MyThread myThread;
    // ...

    public void someMethod {
        // ...
        myThread = new MyThread(mainHandler);
        myThread.start();
        // ...
    }

    // ...

    // The main handler manages messages for mainThread
    // received from myThread
    public Handler mainHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            // ...
        };
    };
}
// File MyThreadClassName.java
public class MyThreadClass extends Thread {
    // ...

    // Handler reference to mainHandler from the parent Thread
    private Handler parentHandler;
    // local Handler manages messages for MyThread
    // received from mainThread
    private Handler myThreadHandler = new Handler(){
        public void handleMessage(Message msg) {
            // ...
        }
    };

    // constructor
    public MyThread(Handler parentHandler){
        this.parentHandler = parentHandler;
        // ...
    }

    @Override
    public void run() {
        // ...
    }

    public Handler getHandler() {
        return myThreadHandler;
    }

    // ...
    // other methods

}

And now the real thing:

// File TestMain.java
package com.indy.testingarea;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.widget.TextView;

// The Class TestMain.
public class TestMain extends Activity {

    // our Thread instance var
    private MyThread myThread;
    // text view influenced by our Thread
    private TextView threadModifiedText;

    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        threadModifiedText = (TextView) findViewById(R.id.text);

        // initializing and starting our Thread
        myThread = new MyThread(mainHandler);
        myThread.start();
    }

    // manages screen touch events
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // prepare a message with touch location data
            Message messageToThread = new Message();
            Bundle messageData = new Bundle();
            messageToThread.what = 0;
            messageData.putFloat("location_x", event.getX());
            messageData.putFloat("location_y", event.getY());
            messageToThread.setData(messageData);

            // sending message to MyThread
            myThread.getHandler().sendMessage(messageToThread);
        }

        return super.onTouchEvent(event);
    }

    // manages messages for current Thread (main)
    // received from our Thread
    public Handler mainHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == 0) {
                // updates the TextView with the received text
                threadModifiedText.setText(msg.getData().getString("text"));
            }
        };
    };
}
  • We have 3 methods:
  1. In onCreate() we initialize everything we need.
  2. In onTouchEvent() we collect and transmit user touch location data to our Thread (myThread object) leaving it to decide what to do – which way to move the text (this actually gives freedom of action to our Thread, maybe someday we’ll want to change its behavior).
  3. handleMessage() from mainHandler instance variable takes care of updating the sliding TextView object (threadModifiedText) when receiving messages from myThread object.
  • We use our Thread as an instance variable for the main Activity because we need access to it from several methods (in onCreate() where we initialize it and in onTouchEvent() where we send messages to its Handler).
  • Our Thread (myThread object) needs to send messages to the main Activity’s Thread and as such it needs access to mainHandler instance variable. As this time myThread’s methods are no longer in the scope of the main Activity’s instance variables we use its constructor for passing mainHandler to myThread.
  • The location of the user screen touch is easily found by using event.getX() and event.getY() methods from onTouchEvent(). Remember that these methods return float values.
  • The visual aspect of the application with colors and text is just a loaded background image

Message usage:

  • In onTouchEvent() method we can see how to create and pack data to a Message object, and then send the message to myThread’s Handler (accessed with the getter method).
  • The data in a Message is added with the help of a Bundle object where it is saved as collection of pairs (keyword, actual data).
  • In the handleMessage() method from the mainHandler we can see how to retrieve data from a Message by using the keyword of the info we need.
  • Take care when retrieving data from a Message’s Bundle object, as we need both the type and the exact keyword we first used to save data in the Bundle object. If we make a mistake here we can have a hard time debugging later because no error will be raised, for primitive types the default values will be returned (0 for int, float, etc) and for Strings null.
// File MyThread.java
package com.indy.testing;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class MyThread extends Thread {
    // constants with display size info
    private static final double STOP_HEIGHT_RATIO = 0.8;
    private static final int HEIGHT = 480;
    private static final int WIDTH = 320;

    // instance vars for managing text move
    private String myText;
    private int currentPosition;
    private boolean moveLeft;

    // reference to mainHandler from the mainThread
    private Handler parentHandler;
    // local Handler manages messages for MyThread
    // received from mainThread
    private Handler myThreadHandler = new Handler(){
        public void handleMessage(Message msg) {
            if (msg.what == 0){
                // stop this Thread if bottom side of the screen was touched
                if ((int)msg.getData().getFloat("location_y") >
                                            (STOP_HEIGHT_RATIO * HEIGHT)){
                    interrupt();
                }
                // set moving direction for the text
                if ((int)msg.getData().getFloat("location_x") < WIDTH/2)
                    moveLeft = true;
                else
                    moveLeft = false;
            }
        }
    };

    //constructor
    public MyThread(Handler parentHandler){
        // initialize instance vars
        this.parentHandler = parentHandler;
        currentPosition = 0;
        moveLeft = true;
        myText = new String("Text changed from MyThread! Do you like it? ");
    }

    @Override
    public void run() {
        super.run();
        try {
            // Thread loop
            while(true){
                // prepare a message with the updated text
                Message messageToParent = new Message();
                Bundle messageData = new Bundle();
                messageToParent.what = 0;
                messageData.putString("text", updateText(myText));
                messageToParent.setData(messageData);

                // send message to mainThread
                parentHandler.sendMessage(messageToParent);

                // update currentPosition value for moving text
                // ternary if form used
                if (moveLeft)
                    currentPosition = (currentPosition == myText.length()) ?
                                       0 : currentPosition + 1;
                else
                    currentPosition = (currentPosition == 0) ?
                                       myText.length() : currentPosition - 1;

                sleep(100);
            }
        }
        catch (Exception e) {
            // Logging exception
            Log.e("TestingAreaLOG","Main loop exception - " + e);
        }
    }

    // getter for local Handler
    public Handler getHandler() {
        return myThreadHandler;
    }

    // updates the text based on the currentPosition
    private String updateText(String text){
        return text.substring(currentPosition) +
                             text.substring(0,currentPosition);
    }
}

We have 3 relevant methods:

  1. MyThread constructor – where we initialize all needed instance variables.
  2. handleMessage() method from myThreadHandler object – manages incoming messages from the main Activity’s Thread and consequently modifies myThread’s variables.
  3. run() method – contains the loop that updates the text and sends messages to the main Activity’s Thread through its Handler.
  • Notice the initialization of the parentHandler variable with the constructor parameter. This will be used to access the main Activity’s Thread Handler. We have also a String (myText) that holds the text to be displayed and an int (currentPosition) used as an “anchor” for changing myText and simulate its moving/rotation.
  • We notice that MyThread doesn’t know the main Activity, it knows and needs only its Handler. In the main Activity we took a different approach, we knew (and actually possesed) a MyThread object and didn’t know its Handler, but accessed it by using a getter. Each of these designs has its advantages.
  • A good way to stop a Thread can be seen in handleMessage() method – usage of the interrupt() command posts an Interrupt request to the current Thread, usually terminating it by throwing InterruptedException (see exact behavior in the official documentation).
  • In our Thread’s main loop (from run() method) we can see again how to prepare and send messages to another Thread – in this case main Activity’s Thread Handler that we received as a constructor parameter.
  • Notice the ternary if form used for updating currentPosition int. That piece of code is equivalent to:
if (moveLeft){
    if (currentPosition == myText.length())
        currentPosition = 0;
    else
	currentPosition ++;
}

So, remember this – ternary operator means the short form:

result = testCondition ? value1 : value2

that is equivalent to:

if (testCondition) {
    result = value1;
}
else {
    result = value2;
}
  • Logging mechanism was used in the catch() block. It is quite simple, Log provides static methods to record various events with different gravities (Log.d() for debug, Log.e() for error, and so on). The Strings passed represent the Tag and the actual message to be logged (more details on logging in some other post).

You can access the source code for this example here.

I hope this little series of examples helped to better understand Threads in Android. If you want more, let me know in a comment and I will continue the tutorial with more on Handler class and the way it can be used to schedule actions for a Thread as well as some general conclusions regarding Threads mechanisms and usages.

19 comments

  1. Eventually I came up to conclusion that using Runnable objects sent to handler is much more efficient than implementing logic for handleMessage(). Using specialized Runnable objects gives to app.design the same advantages as Object Oriented paradigm has vs Procedural paradigm

    • Indeed for a better OO design using specialized Runnable objects is great and some other “tricks” can help further – I hope I’ll soon have the time to continue the Threads/Handlers tutorials and talk more about this kind of issues. But generally speaking I think that each approach has pros and cons. Which one should be used really depends on the actual situation, also on software requirements (with special focus on non-functional ones) and many other small things.

  2. It would be great if you describe using of Looper class. When and why this class will be useful?

  3. Thanks for your effort!

  4. Such nice example, explaining the Android Thread concepts. Looking forward for next tutorial.

  5. Thank you very much! It’s very useful for me.

  6. This tutorial is very good. I learned a lot.
    Thank you! I’ll be looking forward to your next tutorial!

  7. gurkang1

    thanx for sharing ur experience.. was so helpful.. now i totally understand what the handler is, what the connection between handler and threadddddd… thnxxx body thnxxxx so much

  8. Great Work man!It clear me about thread and handler,
    thanks for your tremendous work.
    Actually I am a Android Beginner.It would be very helpful to me if you cover thread more or any other topics which are useful for Animation and Game developing….. like this way

    And at last “”"”"th@nksss @g@in!!!!!

  9. whitetiger

    good tutorial. thank you very much!

  10. Hi Cristi,

    I came across your tutorial and something isn’t clear to me.
    You use MyThread to receive messages from the main thread. However,
    in Android Looper documentation they note that :
    “Threads by default do not have a message loop associated with them”
    I don’t see you are using Looper in MyThread, so how this thread is getting the messages from the main thread ?
    Maybe I missing something here …

  11. Your examples are very usefull and simple, thank you very much

  12. This is the most intelligible tutorial about handler I have found on net, much thanks to cristi!

  13. Hello, your articles here Android – Threads Tutorial – Part 3 | IndyVision.Net to write well, thanks for sharing!

Trackbacks/Pingbacks

  1. Android – Threads Tutorial – Part 2 | IndyVision.Net - [...] Threads Tutorial – Part 3 we will use a special independent class that inherits Thread and we’ll learn more ...

Leave a Reply