In my game, there is an game object class that need to use Handler to post a delay Runnable. However, everything I try to create an Handler in the object class, I receive error message:
Can't create handler inside thread
that has not called Looper.prepare()
I've Googled some solution, but all of them use another solution, not Handler. Is there any solution to use Handler in a normal class? Or any solution to run a Runnable after a determined delay?
I can't use sleep, because it paused all my game!
Thank you.
You are probably creating the Handler from a non-UI thread. Either (1) you attach your handler explicitly to the UI thread by passing the UI thread's looper to Handlers constructor, which means that messages posted to the Handler are also executed on the UI thread, or (2) you create a new Looper for the non-UI-thread: see here.
edit regarding (1): you would have to somehow pass the UI thread's looper to the "game object", for example when it is created. You can get a reference to UI's looper by calling getMainLooper() on a context (e.g. from an activity).
An alternative would be to create the handler in the activity and just pass the handler to your game object.
Related
Is a Handler a Thread or not? If yes, how can we update the UI from this Handler(thread)?
If we use the Looper concept, it may be possible. In this case, does it apply to any threads? I am very much confused about these Threads, Handlers and Loopers. Could anyone please explain them with an example?
Is a Handler a Thread or not? If yes, how can we update the UI from this Handler(thread).
If we use the Looper concept, it may be possible, in this case does it apply to any threads? I am very much confused about this Thread, Handler and Looper. Could anyone please explain them with an example?
The question "What is the difference between a Thread and a Handler" is only about Handlers and Threads, but does not explain Loopers and their behavior. And the accepted answer says that "Handlers on the other hand are background threads that allow you to communicate with the UI thread (update the UI)", but according to the answer by "ben75" below, a Handler is not a Thread. Thus, I do not think this is a duplicate of that question.
premise : A Handler is not a Thread.
A Looper is an Object associated with the Thread from which it is created. As you can guess by it's name a Looper is going to loop over something, but looping over what ? Over a message queue also associated with the same thread.
Next question is: How can I put something in this message queue ?
And here is the Handler. A Handler is always associated with a Looper (which one ? we will see it later). The Handler can play 2 roles (and that's maybe why it is confusing)
First role of the Handler : you must use it to post messages to it's associated Looper (in fact to it's message queue). You can use one of the various Handler.sendMessage* (or Handler.post*) methods to do that. (and note the sendMessageDelayed/postDelayed methods allowing you to post a Message/Runnable to be handled in future)
What is the Looper associated with a Handler ? Very easy : the Looper of the current Thread if you don't specify it; but you can use the constructor with a Looper : new Handler(Looper looper) and in this case the handler is associated with looper in argument.
At this point, we know that :
a Looper is associated with one and only one Thread
a Looper loops over it's associated message queue
as a consequence : there is one message queue associated with one Thread (as soon as we have a Looper for the Thread)
a Handler is always associated with one Looper
a Handler can be used to post message to the message queue
Now, let's see the second part : the message processing/message handling.
First, let's look at the Looper looping over it's message queue.
Is there is a message in the queue ? Yes (i.e. at some point, a Handler has posted it.)
Is it time to handle this message (if it was posted with postDelayed) ? If not, wait a little. If it is time : let's dispatch this message.
Remember that I told that the Handler have 2 roles... and here is the second role of the Handler : a Handler (as indicated by it's name) can handle messages. To be able to handle custom messages you must subclass the Handler class and implements the handleMessage(Message) method.
So, the Looper will simply call the handleMessage of the Handler who posted the message and it's job (i.e. dispatching the messages) is finished (the Looper can move on to the next Message in the queue).
At this point you may ask yourself : "OK I see the interest of delayed messages, but why should I use all this stuff for things to do immediatelly ?"
Remember that the Looper is associated with one Thread and the handleMessage will be called in this Thread. On the other hand, the Handler.post* can be called from another thread. So this mechanism is also very convenient to schedule a job in thread X from thread Y. (particularly useful if the job is affecting the UI and MUST be run in the UI-Thread)
Final note
UI-thread is a first class citizen :
On Android, there is a main Looper associated with the main Thread (i.e. the UI-thread). You can get a reference to it with Looper.getMainLooper(), so you create a Handler associated with the main Looper with :
Handler myHandler = new Handler(Looper.getMainLooper());
and with that you can post a message from any thread to the UI-thread
Should you really use messages and subclassing Handler to use this ? No (not always)
You don't always need to create message explicitly to use this mechanism. You can easily post a Runnable to a Handler and in this case you don't even need to override the handleMessage(Message) because the default implementation of the Handler will simply execute the Runnable (under the hood : a message is created with the Runnable associated to it)
Looper must be prepared (to receive messages)
By default there is no Looper on every thread (by default, there is only a prepared one in the UI-Thread). To prepare a Looper for the current thread : call Looper.prepare()
Handler:
A Handler allows you to send and process Message and Runnable objects
associated with a thread's MessageQueue. Each Handler instance is
associated with a single thread and that thread's message queue. 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.
Now,if you want to update the UI from some other thread that is not the main thread, you will first create a Handler in the main thread and pass it onto any background thread. In the background thread you would do use the post (Runnable r) method to send the message back to the main thread because (read the above paragraph) :) Handlers are not threads, though.
Thread:
A thread is a thread of execution in a program.
Just a generic background processing task.
Looper:
Looper is a class which is used to execute the Messages(Runnables) in
a queue. Normal threads have no such queue, e.g. simple thread does
not have any queue. It executes once and after method execution
finishes, the thread will not run another Message(Runnable).
Sources:
What is the purpose of Looper and how to use it?
What is the difference between a Thread and a Handler
I'm confused by Handler and HandlerThread classes usage. The reason I'm trying to use them is I want to utilize AudioRecord class and its setRecordPositionUpdateListener method (reference). The methos description says:
Use this method to receive AudioRecord events in the Handler associated with another thread than the one in which you created the AudioTrack instance.
And that's exactly what I want - to setup the AudioRecord in the main thread, but receive data in a working thread. I figure I need a HandlerThread so I've created and started one. I've also defined a callback method that implements AudioRecord.OnRecordPositionUpdateListener interface. I want this callback to be called from the worker HandlerThread. What I don't understand now is how to create the Handler to pass to setRecordPositionUpdateListener.
To associate Handler with a certain thread, you should create it by passing corresponding Looper in its constructor. So, if you already have a HandlerThread it can be done in the following way:
Looper looper = myHandlerThread.getLooper();
Handler handler = new Handler(looper);
And that's it, just use this handler in setRecordPositionUpdateListener method and callback will be executed at the worker thread. If you need more explanation on Handler, Looper and HandlerThread, you can take a look here.
Is a Handler a Thread or not? If yes, how can we update the UI from this Handler(thread)?
If we use the Looper concept, it may be possible. In this case, does it apply to any threads? I am very much confused about these Threads, Handlers and Loopers. Could anyone please explain them with an example?
Is a Handler a Thread or not? If yes, how can we update the UI from this Handler(thread).
If we use the Looper concept, it may be possible, in this case does it apply to any threads? I am very much confused about this Thread, Handler and Looper. Could anyone please explain them with an example?
The question "What is the difference between a Thread and a Handler" is only about Handlers and Threads, but does not explain Loopers and their behavior. And the accepted answer says that "Handlers on the other hand are background threads that allow you to communicate with the UI thread (update the UI)", but according to the answer by "ben75" below, a Handler is not a Thread. Thus, I do not think this is a duplicate of that question.
premise : A Handler is not a Thread.
A Looper is an Object associated with the Thread from which it is created. As you can guess by it's name a Looper is going to loop over something, but looping over what ? Over a message queue also associated with the same thread.
Next question is: How can I put something in this message queue ?
And here is the Handler. A Handler is always associated with a Looper (which one ? we will see it later). The Handler can play 2 roles (and that's maybe why it is confusing)
First role of the Handler : you must use it to post messages to it's associated Looper (in fact to it's message queue). You can use one of the various Handler.sendMessage* (or Handler.post*) methods to do that. (and note the sendMessageDelayed/postDelayed methods allowing you to post a Message/Runnable to be handled in future)
What is the Looper associated with a Handler ? Very easy : the Looper of the current Thread if you don't specify it; but you can use the constructor with a Looper : new Handler(Looper looper) and in this case the handler is associated with looper in argument.
At this point, we know that :
a Looper is associated with one and only one Thread
a Looper loops over it's associated message queue
as a consequence : there is one message queue associated with one Thread (as soon as we have a Looper for the Thread)
a Handler is always associated with one Looper
a Handler can be used to post message to the message queue
Now, let's see the second part : the message processing/message handling.
First, let's look at the Looper looping over it's message queue.
Is there is a message in the queue ? Yes (i.e. at some point, a Handler has posted it.)
Is it time to handle this message (if it was posted with postDelayed) ? If not, wait a little. If it is time : let's dispatch this message.
Remember that I told that the Handler have 2 roles... and here is the second role of the Handler : a Handler (as indicated by it's name) can handle messages. To be able to handle custom messages you must subclass the Handler class and implements the handleMessage(Message) method.
So, the Looper will simply call the handleMessage of the Handler who posted the message and it's job (i.e. dispatching the messages) is finished (the Looper can move on to the next Message in the queue).
At this point you may ask yourself : "OK I see the interest of delayed messages, but why should I use all this stuff for things to do immediatelly ?"
Remember that the Looper is associated with one Thread and the handleMessage will be called in this Thread. On the other hand, the Handler.post* can be called from another thread. So this mechanism is also very convenient to schedule a job in thread X from thread Y. (particularly useful if the job is affecting the UI and MUST be run in the UI-Thread)
Final note
UI-thread is a first class citizen :
On Android, there is a main Looper associated with the main Thread (i.e. the UI-thread). You can get a reference to it with Looper.getMainLooper(), so you create a Handler associated with the main Looper with :
Handler myHandler = new Handler(Looper.getMainLooper());
and with that you can post a message from any thread to the UI-thread
Should you really use messages and subclassing Handler to use this ? No (not always)
You don't always need to create message explicitly to use this mechanism. You can easily post a Runnable to a Handler and in this case you don't even need to override the handleMessage(Message) because the default implementation of the Handler will simply execute the Runnable (under the hood : a message is created with the Runnable associated to it)
Looper must be prepared (to receive messages)
By default there is no Looper on every thread (by default, there is only a prepared one in the UI-Thread). To prepare a Looper for the current thread : call Looper.prepare()
Handler:
A Handler allows you to send and process Message and Runnable objects
associated with a thread's MessageQueue. Each Handler instance is
associated with a single thread and that thread's message queue. 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.
Now,if you want to update the UI from some other thread that is not the main thread, you will first create a Handler in the main thread and pass it onto any background thread. In the background thread you would do use the post (Runnable r) method to send the message back to the main thread because (read the above paragraph) :) Handlers are not threads, though.
Thread:
A thread is a thread of execution in a program.
Just a generic background processing task.
Looper:
Looper is a class which is used to execute the Messages(Runnables) in
a queue. Normal threads have no such queue, e.g. simple thread does
not have any queue. It executes once and after method execution
finishes, the thread will not run another Message(Runnable).
Sources:
What is the purpose of Looper and how to use it?
What is the difference between a Thread and a Handler
since several days, I tried to figure out what exactly happens if I execute code in
void function(){
//somePreExecutionCode
new Handler().post(new Runnable(){
#Override
public void run(){
//someCode
}
});
}
It seems like it isn't blocking the UI, so buttons, which calls function() doesn't stuck in the clicked position until someCode has finished.
But if somePreExecutionCode starts a progressBar, the progressBar is shown at exactly the same moment, when someCode has finished.
I know, there are AsyncTasks for, but is there any other possibility?
And whats the difference between
new Handler().post
and
View.post
?
When an Android application is created, system creates a main thread of execution. This thread is referred to as UI thread and all UI related operations happen on this thread in order to avoid synchronization issues.
A Looper instance is created on this thread, which has a MessageQueue data structure. The Looper will be in an infinite loop waiting to read the Message / Runnable instances posted on the MessageQueue. To add Message7 / Runnable to the MessageQueue, Handler is used.
When you create a Handler instance, it will be associated with the current thread of execution and the Looper instance created on that particular thread.
Hence when you post a message via a Handler, the Message is added to the MessageQueue, which will be read in FIFO order by Looper and will be delivered to the target.
new Handler().post() and View.post are bit different.
When you post Messages via View.post, you are guaranteed the Message will be posted on UI thread's MessageQueue, since it internally uses Handler instance created on UI Thread.
If you create Handler instance on UI thread and post the Message using it on any thread, Message will be posted to the UI thread's MessageQueue.
If you create Handler instance on a non-UI thread and post Messages using it, they will be posted on non-UI thread's MessageQueue.
Putting it simply, there are Looper threads, for example, UI thread. Such thread has its own Looper, which runs a message loop for the thread.
Such thread, typically, has a Handler, which processes its Looper's messages - overriding public void handleMessage(Message msg) or executing a Runnable, which was posted to it's looper's message queue.
When you're creating a Handler in the context of UI thread (like you did in your code), it gets associated with UI thread's looper, so your \\someCode runs on UI thread.
I guess, in your use case new Handler().post(Runnable) and View:post(Runnable) are mostly the same, as they both add a Runnable to the UI thread message queue.
But they are not the same.
View:post(Runnable) will add a Runnable to the UI thread looper's message queue;
Handler:post(Runnable) will add a Runnable to its associated thread looper's message queue
My explanation is pretty much intuitive, so correct me anyone if I am wrong.
According to the Android View's documentation:
The Runnable will be run on the user interface thread
According to the Android Handler's documentation:
The Runnable will be run on the thread to which this handler is attached
So, in the Handler's case, you can create it in any thread you want, it's a kind of anchor that will execute the Runnable you provide in the thread it was created in.
In the View.post, you will always execute the Runnable in the uI thread.
A user is getting an error on their phone when executing the code below, I am checking to see if the user is currently on a call or not before I run an AsyncTask making a Web Service call. The reason I am doing this is because some people are losing internet connection when on a call so i check every 5 seconds to see if they are on a call or not. If they are not then AsyncTask gets called
do{
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run() {
onCall = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
.getCallState() != TelephonyManager.CALL_STATE_IDLE;
if(!onCall){
new CallRegWS().execute();
}
}
},5000);
}while(onCall);
I do not have the full stack trace only this showing me the error
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
obviously not too helpful but that is all I have to go on. they keep getting that error so it must be happening when I create the handler.
All this is done in the main thread so I dont know what the problem is, any insight on how I could fix this?
Update
this is called from a service and the method is in a separate class
Try Handler handler = new Handler(Looper.getMainLooper());
Also, see this post regarding this error: http://levinotik.com/loopers-handlers-runtimeexceptions-explained/
First of all you have to know that, Handlers automatically attach to the thread where are created as specified in the documentation:
Handler Class Overview
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. 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. Handler | Android Developers
Now, taking that on count and since the current thread don't have a message queue, in order to work properly the thread needs an actual "Queue", and that's exactly what the system is telling you to do, by calling Looper.prepare() you are creating a Message Looper within the thread you created because by default Threads do not have a Message looper as mentioned in documentation:
Looper Class Overview
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped. Looper | Android Developers
In other words and in a simple manner, the Main UI DOES have a Message Queue already prepared, and that's why you don't see that error when calling new Handler() within "onCreate, onStart, onResume etc...", but for any worker thread created the system needs a queue to send the messages to when using handlers, although the code doesn't show it, i bet that code is being executed in a worker thread either normal Thread or doInBackground method of an AsyncTask and that's what causes the error, to avoid it remember to always call Looper.prepare before creating a handler from a worker thread.
Hope this Helps.
Regards!
How do you know this is running on the Main thread? And when and where is this getting called from? Instead of creating your handler right before you use it, create it in the onCreate method of your Activity or your Service (depending on what this is).Then in your onDestroy null the value out.