I'm wondering how Handlers are processed in Android/DalvikVM. I'm writing an application for Android, and in one class I have a Handler method which receives messages from another class. Will the Handler method act as a Thread and be asynchronous to the run() method in the same class, or will it wait until a line of code in the run() method is finished (sort of atomic operation)? Or something else?
I'm wondering, because I want to add messages to a queue in the Handler method, and process and remove them in the run() method (producer-consumer).
My code structure:
public class Parser implements Runnable {
public void run() {
while(true) {
// Remove a byte from the ring buffer and parse it
byte b = Ringbuffer_read();
// Parse
try {
Thread.sleep(40);
} catch (InterruptedException e) {}
}
}
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
// Store all the received bytes in the ring buffer
for (int i = 0; i < msg.arg1; i++) {
Ringbuffer_store(((byte[]) msg.obj)[i]);
}
break;
}
}
};
}
When will the code in the handler run? Does it interrupt the code in the run() method at any point? Do I have to have some synchronization or semaphores or something around the code in the run() and handler method so that I don't corrupt my buffer?
An Android Handler associates itself with whatever thread it is created in (assuming that thread has a looper already). By default in Android callbacks run on a thread named "main" which is also called the ui thread. Regardless of what thread the post method is called from the handleMessage method will be called from the thread that the Handler was created in (usually the "main" thread). Because the handleMessage method is always called in the same thread, only one message will be processed at a time.
If your plan is to have only a single consumer then Handler is a good choice. You will not need to remove messages from your consumer (the Handler), instead they will simply arrive in handleMessage for processing. If you want to do processing on the "main" thread then you just make a new Handler, if you want to do processing in the background to avoid ANRs you will likely want to use HandlerThread. Here's an example of a Handler running on it's own background thread:
HandlerThread handlerThread = new HandlerThread("Consumer");
handlerThread.start();
Handler consumer = new Handler(handlerThread.getLooper()) {
public void handleMessage (Message msg) {
}
};
Notice that in the description above class does not come into play at all because classes are how code is structured which is unrelated to what thread the code is executed on.
Related
Consider the following snippet:
Looper.prepare();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
getLooper().quitSafely();
}
};
for(int i = 0; i < urls.size(); i++) {
useCaseProvider.get().execute(callback, handler, urls.get(i), threadPool);
}
Looper.loop();
//Continue processing the results of all the use cases after the
//loop has been asked to terminated via the handler
A little background: I'm doing some processing on the UI thread where I will need to ping a large about of devices and do something with the result. I need to perform the requests in parallel to be efficient.
Question: If one of these use cases somehow executed fast enough and made a callback before I was able to hit Looper.loop(); would the message be queued or just lost? Callbacks are being posted back to this thread by the handler posting a runnable to the original thread.
Assuming you have invoked Looper.prepare() prior to your useCaseProvider delivering results, you should be fine.
If Looper.prepare was not called you should be seeing RuntimeException being thrown.
The Looper object is tied to a thread local which hosts the message queue. The Looper.prepare function will construct this message queue at which point you can begin queuing up messages. Once you fire Looper.loop() that's when those pending messages will begin to execute.
Looking at the snippet, I'm not too sure how things are tied together.
Generally you want to construct a looper like this:
private static final class MyThread extends Thread {
private Handler mHandler;
#Override
public void run() {
Looper.prepare();
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// handle message
}
};
Looper.loop();
}
public Handler getHandler() {
return mHandler;
}
}
I'm assuming your thread pool is then a pool of MyThread threads, each of which have their own Looper. The thread pool should initialize your threads so once you deliver a Runnable to be executed by your thread, the run() method should have the Looper initialized.
On the other hand, if you wish to associate your Handler with a particular looper (ie. you are not constructing the Handler within a thread like above) then you should be passing the Looper thread in to the constructor like:
Handler h = new Handler(myLooperThread);
If you don't specify that, then the handler uses the thread in which it was created to grab that thread's Looper from the ThreadLocal object.
Lastly if your intentions are to have messages delivered on the Handler which is associated with the UI thread then you should not be concerned about calling Looper.prepare or Looper.loop. This is handled by the Activity.
I have one thread that does lot of time consuming tasks. The tasks are being done in the native part in c++. I would like to cancel the operation that is being done in the native, the code for that is place. I can reset everything.
mWorker = new WorkerThread("Worker thread");
mWorker.start();
//From Main thread:- Interrupting
mWorker.interrupt();
if(mWorker.isInterrupted()) {
Log.i(MOD_TAG, "Worker thread is interupptedd!!! ");
}
//Worker thread
public class WorkerThread extends Thread implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted()) {
Looper.prepare();
mHandler = new WorkerHandler();
Looper.loop();
}
class WorkerHandler extends Handler {
#Override public void handleMessage(Message msg) {
try {
switch(msg.what) {
//do something native code
}
}
catch (Exception e) {}
}
}
}
}
Even if the workerthread is interrupted I cannot send any message to the worker thread while the worker thread is doing processing. Can I do something to post a message to workerthread or do something else that could let me call a native method within the same thread.
In your example, I don't understand what that Handler is doing inside the Thread. Once you call loop() within the run, that call will block until the looper is stopped via quit() or quitSafely(). The call is basically just a loop which reaps a queue for messages. Your check for interrupt will never happen.
I would recommend something like this. If you want your code to be managed by a handler you would do something like:
HandlerThread handlerThread = new HandlerThread("NativeHandler");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
public void handleMessage(Message msg) {
someObject.callNativeLongRunningFuction();
}
};
However interrupt still won't do anything because the looper only handles one message at a time. So if it is stuck handling callNativeLongRunningFunction(), that is not going to help you really either. If you want to have interrupt stop the ongoing execution of the jni call, the I don't think this approach will work at all with the given information. Interrupt in java only sets a flag and when there is a call to wait(), it will throw an exception when that flag is checked and also set. But for a jni call there isn't a call to wait(), the java stack is sort of blocked but it is not in the middle of a wait() either. So unless you check interrupted within the native runtime, that function will continue to run. Overall I am guessing this probably would not be what you really want.
If that is so, I would recommend something like this instead.
public class NativeThreadTask {
public native void start();
public native boolean isRunning();
public native boolean cancel();
}
Inside the native implementation of that class, you would then use a pThread to call your native long running function. Start and Cancel would manipulate that pThread which would run the expensive function in a separate thread. Using pthread_cancel you can interrupt that pthread instance too. This moves the long operation off your thread and out of your runtime, while still allowing you to control when the pthread interrupt mechanism is invoked but over the jni bridge. If you don't even want to interrupt and if the long running native call is iterating over a large amount of data, then it might be worthwhile to have cancel() simply change bool that is evaluated within each iteration of the native function's loop.
So with the given example you could probably do something like this.
NativeThread nativeThread = new NativeThread();
Handler handler = new Handler() {
public void handleMessage(Message message) {
NativeThread nativeThread = (NativeThread)message.obj;
switch(message.what) {
case 0:
if (!nativeThread.isRunning()) {
nativeThread.start();
}
break;
case 1:
if (nativeThread.isRunning()) {
nativeThread.cancel();
}
break;
default:
}
}
};
I have a thread where I need to periodically perform some checks, get files from the web, and send messages to the main UI thread. I even need to use UI thread parameters (like the map visible area) on each loop of the worker thread. So I suppose that i need to implement bidirectional communication between UIthread and workerThread.
Another problem is that I need to save the identifier of each marker added to the map. I want to save the result of map.addMarker inside my custom array stored in my worker thread. this means that from the uithread, where i update the map, i should tell the workerThread to update the array of markers..
This is a sample of my actual worker thread:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
My actual problem is that when the UI thread ends processing the message received from the worker thread i should perform an action on the worker thread.
I thought 2 solutions:
1)wait on the worker thread till the message has been processed by the UI thread
2)process the message on the UI thread and then send a message to the worker thread.
I don't know how to do the solution1, so i tried the solution2. I tried adding a looper to my worker thread (RUN sub), this way:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
#Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// Act on the message received from my UI thread doing my stuff
}
};
Looper.loop();
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
The problem is that after the Looper.loop() no line of code is executed. I read that this is normal. I read many articles but I didn't understand how should I allow the execution of my while loop, and simultaneously process messages coming from my UI thread.
I hope the problem is clear. Suggest me the best solution.
don't do this:
while(true){
sleep(2000);
it's awfully bad on so many levels. if you need some background processing, use AsyncTasks, if you need a repeating event, use:
private Handler mHandler = new Handler();
private Runnable mSomeTask = new Runnable() {
public void run() {
doSomething();
}
};
and then somewhere in the code:
mHandler.postDelayed(mSomeTask, 100);
this will make your program work faster, jam less resources and basically be a better Android citizen.
I realize this is a very old question, but for periodic task scheduling, use this code:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> periodicTask = scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// do some magic stuff here
// note however, that you're running in background!
Log.d("PeriodicTask", "Doing something....");
}
}, 0 /* initial delay */, 10 /* start every 10 seconds */, TimeUnit.SECONDS);
and when you need to stop the periodic task, just issue
periodicTask.cancel(true);
I'm having a bit of trouble understanding how to use the Looper prepare()/loop()/quit() logic.
I have three threads: one is the UI thread, one is a game logic thread and the last is a network communication thread (a background thread, lives only while being used).
The game thread has many dependencies on the results of the network calls, so I wanted to spin the network thread off of the game thread and have a Handler post the result back.
Of course, since the UI thread is not involved I need to call Looper.prepare()... somewhere. I thought it should be called in the game thread, but I can't do that because loop() takes it over.
How do I go about posting back to the game thread from network thread with my handler?
What's going on is that once you call Looper.prepare() followed by Looper.loop() on a Thread, all that Thread will ever do is service its MessageQueue until someone calls quit() on its Looper.
The other thing to realize is that, by default, when a Handler is instantiated, it's code will always execute on the Thread it was created on
What you should do is create a new Thread and in run() call Looper.prepare(), setup any Handlers, and then call Looper.loop().
Bearing these things in mind here is the basic pattern I use a lot of places. Also, there's a good chance you should just be using AsyncTask instead.
public class NetworkThread extends Thread {
private Handler mHandler;
private Handler mCallback;
private int QUIT = 0;
private int DOWNLOAD_FILE = 1;
public NetworkThread(Handler onDownloaded) {
mCallback = onDownloaded;
}
public void run() {
Looper.prepare();
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
// things that this thread should do
case QUIT:
Looper.myLooper().quit();
break;
case DOWNLOAD_FILE:
// download the file
mCallback.sendMessage(/*result is ready*/);
}
}
}
Looper.loop();
}
public void stopWorking() {
// construct message to send to mHandler that causes it to call
// Looper.myLooper().quit
}
public void downloadFile(String url) {
// construct a message to send to mHandler that will cause it to
// download the file
}
}
Could you tell some examples for what you are using your network thread? I think you can solve your problems without using Looper.
You can use ASyncTask to perform background task that may update some values in your UI thread. If user has to wait until background operation will be finished, you can show ProgressDialog and block application in OnPreExecute method, and then hide it in onPostExecute.
As I said, please describe more your needs and target which you want to achieve.
I've more than one Handlers in an Activity. I create all the handlers in the onCreate() of the main activity. My understanding is the handleMessage() method of each handler will never be called at the same time because all messages are put in the same queue (the Activity thread MessageQueue). Therefore, they will be executed in the order in which are put into the Queue. They will also be executed in the main activity thread. Is this correct ?
public void onCreate() {
this.handler1 = new Handler() {
#Override
public void handleMessage(Message msg) {
//operation 1 : some operation with instanceVariable1
super.handleMessage(msg);
}
};
this.handler2 = new Handler() {
#Override
public void handleMessage(Message msg) {
//Operation 2: some operation with instanceVariable1
super.handleMessage(msg);
}
};
this.handler3 = new Handler() {
#Override
public void handleMessage(Message msg) {
//Operation 3: some operation with instanceVariable1
super.handleMessage(msg);
}
};
}
From the docs "When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue."
So you're right, they will run in the order that you queue them on the UI thread (since you are going to create them in onCreate).
One message per time, and per thread, and per handler.
Every new Handler(...) instance is bound, explicitly or implicitly, to Looper instance, and only once.
Looper instance, is already created somewhere with Looper.prepare() call
//usually obtained by Activity.getMainLooper() or Looper.myLooper()
Looper.prepare() uses ThreadLocal variable sThreadLocal (static field) to have one Looper instance per thread.
( It works same like hashMap.put(Thread.getCurrent(), new Looper()) )
every looper has its own private MessageQueue
every Looper instance has its main method loop()
loop(){
while(true){
Message msg = messageQueue.next();
msg.target.dispatchMessage(msg);
}
}
every message have a (Handler) target is set, and exception is thrown(within MessageQueue.enqueueMessage()) if it does not.
since Handler cannot be bound to several Loopers is does so every handler receives only one message at time and only with msg.target==handler
so sendMessage() or postMessage() works something like this:
handler.post(Message msg){
Looper.sThreadLocal.get(Thread.getCurrent()).messageQueue.push(msg);
}
so call stack , while handle message, should look something like this:
Looper.myLooper()-> Thread.getCurrent()-> Looper-> MessageQueue.next()-> Message-> Message.target-> Handler-> dispatchMessage()-> handleMessage()