In my android application I created 2 handlers. One handler received message and waiting(calling wait();). At this point if I post messages to second Handler, it is not receiving. After some time I am getting dialog box saying Application not responding "Force Close" or "Wait buttons".
I think because of wait() in one handler, blocking second handler to receive messages.
Please suggest me solution to this problem.
You should create two threads and create a handler in each of these two threads and call Looper.loop in the run method of both the threads
class HandlerThread1 extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
Same way create HandlerThread2 and start both the threads.
You should never call wait in Ui thread, that is the reason you are getting App not responding popup. You can always post another message with duration instead of wait
Related
I'm a little confused about something. Basically, I'm spawning a thread, and in addition I want to run a message loop in that thread. I'm basically doing the following:
This is straight out of the Android Looper class API documentation. However, my application always gets stuck at Looper.loop() and never returns from it. My current work around for this, is to just create a handler in the main thread (or UI thread) and send messages to that thread instead. However, for the sake of cleanliness and to just make the flow of my application make sense, I'd much rather send my messages to the thread I'm creating.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
// The rest of the code below is a control loop
}
}
Any thoughts on what might cause Looper.loop() to never return?
Looper.loop creates an infinite loop and only stops when you call quit
http://developer.android.com/reference/android/os/Looper.html#loop()
This may work
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
while(true){
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
}
// The rest of the code below is a control loop
}
}
The question is, where I tell my Thread to use mHandler for the Looper?
Thank you.
I am using the below code:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
The question is, where I tell my Thread to use mHandler for the
Looper?
You don't need to tell it explicitly, because the system (framework) does it for you. When you instantiate the Handler, it will automatically obtain access to the message queue of your current Thread. Quoting your comment:
How the system know to send the message to the mHandler Handler?
I'll detail it below.
This is the constructor of android.os.Handler in Android:
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
As you can see, first it obtains the Looper of your current Thread. The source code of Looper.myLooper() is as follows:
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
It obtains it from the thread local storage. Later, when you send a Message with this Handler, the Handler actually sets itself as the recipient of the Message: this is how the Looper will know where to dispatch the Message when it arrives. In details:
When you call mHandler.sendMessage(), eventually this code runs (among many other code lines):
MessageQueue queue = mQueue;
boolean sent = false;
if (queue != null) {
msg.target = this; // msg is your Message instance
sent = queue.enqueueMessage(msg, uptimeMillis);
}
As you can see, it sets the Handler instance as the target of the Message. So, later, when the Message is dispatched, it will contain the Handler as its target. This is how the Looper will know which Handler it should dispatch it to. In details, when you call Looper.loop(), the following happens for each of your Message instances in the queue:
msg.target.dispatchMessage(msg);
The dispatchMessage() code is the following:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Notice the last handleMessage(msg) call -- this is exactly your handleMessage(msg) override!
To have a better understanding, create a normal Thread and try creating a Handler in the run() method of that thread. You'll get a RuntimeException saying:
Can't create handler inside thread that has not called
Looper.prepare()
Now calling Looper.prepare() in the run() method before creating a Handler would create a new Looper object associated with the calling thread. The source of your confusion is that Looper.prepare() does not take a Thread as argument. It need not, since it's a static method, which internally gets the ThreadLocal of the currently running thread. There can be at most one Looper associated with any Thread.
Now, calling new Handler() would associate the new Handler object with the Looper of the current Thread by internally calling Looper.myLooper(). You can create more than one Handler each with its own Callback in the same Thread. All Handlers would get their messages from the message queue of the same Looper.
You don't tell anything. From the Handler documentation:
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.
The handler is automatically bound to the thread's message queue. You only implement the callback, and the system will take care of everything, ie dispatching and processing the messages. Actually I agree that, using two static methods like Looper.prepare() and Looper.loop() and automatically infer things, makes the pattern feels like black magic :)
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.
How do I get the message queue of the main thread from another thread? Looper.getMainLooper() gets the main thread's looper but I am unable to find a way to get the MessageQueue for another thread's looper. Moreover, how do I get the handler for the main looper? I am unable to find any way to get it.
#r.v,
I had a similar need. I wanted to know when the MessageQueue is empty and when I post something for it to do and I want to know when it becomes empty with nothing remaining to do. I looked at the MessageQueue.IdleHandler and found that it didn't behave as I wanted to I came up with another solution.
In my case I wanted to use the Looper/Handler mechanism to sequentially execute file downloads. Basically each download I want to execute is wrapped in a Runnable. I only want one at a time to be running, so this pattern works well without having to dig into the nuts and bolts of a more involved threading solution. Additionally, I wanted to know when I first put something into the queue and it begins its work, and wanted to know when it was completely done (queue is empty).
I was able to use the handler's message mechanism to achieve this. The messages are handled in sequence with the Runnables, so you can strategically place messages in the queue to help you know the conditions of the queue. Unlike with Runnables in the Handler's queue, there are some query and removal abilities for messages that ultimately provide the solution.
What I do is each time I add a runnable to the Handler (via Handler.post), I also remove all instances of the custom QUEUE_EMPTY message, then add a fresh QUEUE_EMPTY message. This ensures that I have a QUEUE_EMPTY message at the end of the queue. Once I encounter the QUEUE_EMPTY message in my subclassed Handler, I know that I'm at the end of the queue. Additionally, if I don't find a QUEUE_EMPTY message in the queue when I go to add a runnable, I know that the queue was empty and the thread was idle.
As some will quickly point out, there are some real inefficiencies with this solution. Having to iterate through the queue for these "marker" messages could be a real performance issue if there were a large number of entries in the queue. In my case, I'm dealing with only a handful of file downloads at a time so any performance penalties are negligible. If you have a similar situation, I think this is a pretty reasonable solution. It would have been nice for the Android SDK to provide these basic abilities to the MessageQueue. I agree ideally you wouldn't want to mess with the MessageQueue, but knowing when it is idle/working/empty seem like reasonable things and I'm sure there are numbers of scenarios when there is value knowing these things.
class DownloaderThread extends Thread
{
private static final int QUEUE_EMPTY = 9999;
private MyHandler handler;
#Override
public void run()
{
try
{
Looper.prepare();
handler = new MyHandler();
Looper.loop();
}
catch (Throwable t)
{
Log.e(TAG, "halted due to an error", t);
}
}
public void post(Runnable r)
{
if(!handler.hasMessages(QUEUE_EMPTY))
{
Log.v(TAG, "Download queue was empty. First element being added.");
}
handler.post(r);
handler.removeMessages(QUEUE_EMPTY);
handler.sendEmptyMessage(QUEUE_EMPTY);
}
class MyHandler extends Handler
{
#Override
public void handleMessage(Message msg)
{
if(msg.what == QUEUE_EMPTY)
{
Log.v(TAG, "Download runnable queue is empty!");
}
}
}
};
After you get the main threads looper, you should just be able to call myQueue to get the main threads MessageQueue.
http://developer.android.com/reference/android/os/Looper.html#myQueue%28%29
Use the Handler class to interact with a Looper's message queue.
To interact with the main thread's message queue,
Handler mainHandler = new Handler(Looper.getMainLooper(), new Callback() {
#Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
});
mainHandler.post(...);
mainHandler.sendMessage(...);
mainHandler.removeMessage(...);
Now you can send, remove and receive messages.
Dear all
I have an android activity and a normal .java class which contains an "onChange" function(the function is called whenever properties of my skype contact are changed)
When I try to call an alertdialog.show() in my onChange function, I got error "Can't create handler inside thread that has not called Looper.prepare()", what should I do to show a message in my activity? thanks in advance
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
From the android documentation :
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
Also never ever have UI calls in a (worker) Thread. It is bound to throw exceptions.