Concepts
- Handler:
- According to Android Document, 2 usages of handler are:
- "to schedule a message or object to be executed in future". In other words, it could receive messages and perform action.
- "the enqueue and action to be performed on a different thread", same process.
- when sending a message, the message is placed in a MessageQueue associated with a
Looper
. A Looper is used to manage a message queue for a thread and it allows a thread to process messages one at a time.Handler
constructs a message viaobtainMessage
fucntion, and sends the message viasendMessage
. - when receiving a message, a Looper retrieves the messages from the queue and dispatches them to appropriate Handler. Receiving is done via function
handleMessage
. sendMessage
sends a message which is received in thehandleMessage
in the thread attached to this handler.- the "sending_message_class" and the "receiving_message_class" can be on different threads but must be associated with the same
Looper
for communication to occur via message queue.
- Looper:
- According to Android Document, Looper is class that "runs a message loop for a thread". In other words, user "can initialize current thread as a looper. This gives a chance to create a handler that then references this looper". (see function
prepare
in Android Document). - MainLooper is the application main looper, lives on the main thread of the application. Looper and handler can live on child threads.
- MessageQueue: is the class that holds the list of messages to be dispatched by a Looper. Messages are added to
Looper
viaHandler
.
- The message should include at least a custom code
what
to identify the type of message. Message can includearg1
,arg2
which stores primitive data orobj
which is object . (see functionobtainMessage
function and its arguments in Android Document )
The following program implements 2 classes: MySensor and MyReceiver. MySensor can send a message that includes and EventCode and and integer the MyReceiver. Both classes communicate through default Looper.

Implementation
Using default Looper
#include <iostream>
#include <android/looper.h>
#include <android/handler.h>
using namespace android;
enum EventType {
DIAGNOSTIC_SIGNAL,
CONTROL_SIGNAL,
STOP_SIGNAL
};
class MySensor : public Handler {
public:
void sendSignal(EventType event, int data) {
Message msg = obtainMessage(event, data);
sendMessage(msg);
}
};
class MyReceiver : public Handler {
public:
void handleMessage(const Message& msg) {
EventType event = (EventType) msg.what;
int data = msg.arg1;
switch (event) {
case DIAGNOSTIC_SIGNAL:
std::cout << "Received DIAGNOSTIC_SIGNAL with data: " << data << std::endl;
break;
case CONTROL_SIGNAL:
std::cout << "Received CONTROL_SIGNAL with data: " << data << std::endl;
break;
case STOP_SIGNAL:
std::cout << "Received STOP_SIGNAL with data: " << data << std::endl;
break;
default:
std::cout << "Received unknown signal with data: " << data << std::endl;
break;
}
}
};
int main() {
MySensor sensor;
MyReceiver receiver;
sensor.sendSignal(DIAGNOSTIC_SIGNAL, 123);
sensor.sendSignal(CONTROL_SIGNAL, 456);
sensor.sendSignal(STOP_SIGNAL, 789);
return 0;
}
Notes: MySensor
and MyReceiver
can run on multiple threads, and use custom Looper. So long as they use the same Looper, the messages can be sent between the two components. The looper is passed into the constructor of MySensor
and MyReceiver
.
Using custom Looper
- In the below programs, we have 2 threads. The custom
Looper
is created on the main thread. - MySensor, and MyReceiver are each created (they could be on different threads, but in this program they are both on main thread). They are handler classes and bounded to the Looper via the parameterized constructor:
MySensor(sp<Looper> looper) : sl:Handler(looper) {}
MyReceiver(sp<Looper> looper) : sl:Handler(looper)
- A Handler is always bound to a Looper, and subsequently bound to the thread associated with the
Looper
#include <iostream>
#include <android/looper.h>
#include <android/handler.h>
#include <thread>
using namespace android;
enum EventType {
DIAGNOSTIC_SIGNAL,
CONTROL_SIGNAL,
STOP_SIGNAL
};
class MySensor : public Handler {
public:
MySensor(sp<Looper> looper) : Handler(looper) {}
void sendSignal(EventType event, int data) {
Message msg = obtainMessage(event, data);
sendMessage(msg);
}
};
class MyReceiver : public Handler {
public:
MyReceiver(sp<Looper> looper) : Handler(looper) {}
void handleMessage(const Message& msg) {
EventType event = (EventType) msg.what;
int data = msg.arg1;
switch (event) {
case DIAGNOSTIC_SIGNAL:
std::cout << "Received DIAGNOSTIC_SIGNAL with data: " << data << std::endl;
break;
case CONTROL_SIGNAL:
std::cout << "Received CONTROL_SIGNAL with data: " << data << std::endl;
break;
case STOP_SIGNAL:
std::cout << "Received STOP_SIGNAL with data: " << data << std::endl;
break;
default:
std::cout << "Received unknown signal with data: " << data << std::endl;
break;
}
}
};
void runSensor(sp<Looper> looper) {
MySensor sensor(looper);
sensor.sendSignal(DIAGNOSTIC_SIGNAL, 123);
sensor.sendSignal(CONTROL_SIGNAL, 456);
sensor.sendSignal(STOP_SIGNAL, 789);
}
void runReceiver(sp<Looper> looper) {
MyReceiver receiver(looper);
looper->pollOnce(-1);
}
int main() {
sp<Looper> looper = new Looper(false);
std::thread sensorThread(runSensor, looper);
std::thread receiverThread(runReceiver, looper);
sensorThread.join();
receiverThread.join();
return 0;
}
- To send a message to Looper, we need to construct a message using
obtainMessage
and then send the message to the MessageQueue using eithersendToTarget
orsendMessage
function. - The difference between
sendToTarget
andsendMessage
is thatsendToTarget
is used when the sender wants to send the message back to the handler that created it, whereassendMessage()
is used when the sender wants to send the message to a different handler. - In the above program, Sensor and Receiver were created on different threads. Consequently, the handlers are different, but still bound to the same looper!!!
sendMessage
allows sending message to the receiving handler on a different thread. The handler s can communicate because they are bounded to the same Looper.
// to construct message:
Message msg = obtainMessage(event, data);
// to send the message to the same handler that the message is constructed:
msg->sendToTarget();
// to send the message to a different handler:
sendMessage();