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.
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
}
}
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
I'm developing an android app, i have a separate class that extends Thread class, here i call a service and fetch data, now i need to know when this thread is completed and on completion its shows me a Toast.
Like
"Successful"
Is there any method like onPostExecute() in AsyncTask Thread?
Thanks
Display a toast is different that modify Views component because toast can be displayed from every thread while views need to be accessed only from the main thread.
So, if you need just to display a Thread just call Toast.makeToast(...).show() wherever you are.
Anyway, you can send messages from a backgrund thread to the main thread using the Handler class:
http://developer.android.com/reference/android/os/Handler.html
http://developer.android.com/guide/faq/commontasks.html#threading
i hope you are using thread like this..
.....
new Thread(new Runnable() {
public void run() {
YourMetod(); //you want to execute first
finishedHandler.sendEmptyMessage(0);//when first method is executed completly you need to call this
}
}).start();
....
create a handler in your class
like this
private Handler finishedHandler = new Handler() {
#Override public void handleMessage(Message msg) {
//create your toast here
}
};
try this hope help
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()
I have an app with a two threads - main and data loader. When data loader finishes it posts a Runnable object to the main thread (as described in the DevGuide), but it never gets delivered and run.
Here's the basic code:
class MyApp extends Application
{
public void onCreate()
{
LoaderThread t = new LoaderThread();
t.start();
}
private class LoaderThread extends Thread
{
public void run()
{
SystemClock.sleep(2000);
boolean res = m_handler.post(m_runnable);
if(res)
Log.d(TAG, "Posted Runnable");
}
}
private final Handler m_handler = new Handler();
private final Runnable m_runnable = new Runnable() {
public void run()
{
Log.d(TAG, "Hey, i'm runnable!");
}
}
}
Also it maybe important to note that I ran this code as a unit-test derived from an ApplicationTestCase:
class MyAppTest : public ApplicationTestCase
{
public MyAppTest()
{
super(MyApp.class);
}
public void testLoading()
{
createApplication();
// few asserts follow here...
}
}
So this fails. Runnable never gets run() called, although the log indicates that it has been posted successfully.
I also tried to send simple messages instead of posting runnable (m_handler.sendEmptyMessage(1) for example) - they never get delivered to handler's callback in the main thread.
What do I miss here?
Thanks in advance :)
A Handler requires a Looper in order to work. The Looper provides a message queue required by the Handler.
All instances of Activity have a Looper as one is used to process UI Events, but you can create your instance of Looper elsewhere.
Have a look in your Log output to see if Android is complaining about the absence of a Looper.
If it is, you might be able to fix by add the following to the top of your onCreate() method:
Looper.prepare();
m_handler = new Handler();
Looper.run();
And remove the initialisation of m_handler from later in your code.
Handler only works in an Activity AFAIK. You are attempting to use it in an Application.
An alternative to calling Looper.prepare() is to call new Handler(Looper.getMainLooper()). The problem with calling Looper.prepare() is that it will throw an exception when there is already a looper on your thread. Chances are you are writing code that has to run under different environments and this solution will handle more cases.
See:
AsyncTask and Looper.prepare() error