I have a thread, initialthread that executes a task every n seconds. This is enclosed in activity A. i have a message handler on activity B.
mHandler = new Handler(){
public void handleMessage(Message msg)
{
//perform task
executetask();
}
};
Will this handler excutetask() whenever the initialthread finishes executing??
thanks
It will execute whenever you pass the massage from the initial thread.
I mean whenever you call .sentMessage() from the initial thread.
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
}
}
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);
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 have written a handler that calls the method every time interval. I want to remove that handler in on destroy(). The code i use as follows, In Oncreate()
private final Handler _handler = new Handler();
public int DATA_INTERVAL = 30 * 1000;
Runnable getData;
getData = new Runnable()
{
#Override
public void run()
{
recieveData();
}
};
_handler.postDelayed(getData, DATA_INTERVAL);
and in ondestroy(), i use,
_handler.removeCallbacks(getData);
But removecallbacks not work. It calls after exiting the activity.
removeCallbacks(Runnable r):
Remove any pending posts of Runnable r that are in the message queue.
so removeCallbacks(..) only stops pending messages (Runnables) not currently running runnable so if you want to stop currently running Runable then use a Boolean varaible for Stoping Thread when user Exit from your app.
see this post for removeCallbacks not stopping runnable
You are not showing the most important part of the code which is the receiveData method. As you said you are running the task periodically, you must be calling again postDelayed from inside that method to reschedule the task. Probably background threads involved as you cannot do networking on the main thread.
You most likely have a race condition when exiting the Activity. onDestroy runs first and then the task is posted again.
You should use
handler.removeCallbacksAndMessages(null);
Then all handler callbacks will removed.
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()