If I've got it right a handler works like a queue. So my simple question is if I first postDelayed and after that do I regular post. Will the second post run after the first delayed post?
handler.postDelayed(someMethod(), 10000);
handler.post(someOtherMethod());
Will the someOtherMethod() run after someMethod()
No it won't. The second one will be performed immediately when all pending handler requests (so on the UI thread) are done. The first will be appended after 10 seconds.
Hint: The handler takes a Runnable, so it looks like that:
handler.post(new Runnable {
public void run() {
doSomething();
}
}
Update based on comment:
The handler invokes the posted runnable on the thread on which new Handler() was called.
No, 2nd post will run as soon as possible (before 1st).
No, handler posts are asynchronous. what handler.post() does it that it adds the runnable to the message queue. handler.postDelayed() adds the runnable to the message queue immediately , but the timer will be set to delayed ms , after which the runnable will be executed.
so all post does is , to add the runnable to the message queue.
Related
As google says:
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.
And i expect when i create a Handler in main thread (UI thread) it attached to this thread so it cause to freeze ui till end it's task. But in test this not happen and it is acts like it is on a backgound thread and do his task parallel.
I used to create Handle like this:
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i < 35000; i++) {
log.i(TAG,"log in Handler:"+i);
}}
};
mainHandler.post(runnable);
log.i(TAG,"log outSide");
In mainActivity (so handle should bound to Main thread). So what is the problem with this or am i create the handler in wrong way?
Some friends notice that doSomthing() is not complicated enough but why we see "log outSide" before "log in Handler:" if they are in a same thread.
Actually, It's working as you expected, Your handler is currently associated with your main thread because it is created in it and your task is also running on the same. Try to add Thread.sleep(1000) method inside your for loop then you will see the freeze in your UI.
Your current code runs with a complexity of O(1) since your N is constant, and your phone is capable enough to run this in a fraction of a second that's why you are not observing any freeze in your UI during the test.
Some friends notice that doSomthing() is not complicated enough but why we see "log outSide" before "log in Handler:" if they are in a same thread.
This is because of the delay in posting the Runnable to the Handler. Even though the Handler is created with the main thread's looper, there is still a small amount of delay between when post is called and when that Handler message is put into the Handler's queue and executed on the thread.
"log outside" runs instantaneously, so you see that log before the log within the Handler.
I have a set of instructions that needs to be executed repeatedly.
The repeat delay is variable (the delay is taken from a file).
The repeat time must be very precise (milliseconds precision).
I have tried to use a Handler with postDelayed but the accuracy is lost in time. This happens because the repeat frequency is more than 10 times/second.
Any idea is more than welcomed!
Here is the Handler example:
new Runnable() {
#Override
public void run() {
mHandler.postDelayed(this, delay);
barometerResult.gotBarometer(barometerValueModelList.get(i).getBarometerValue());
}
}.run();
I don't think it's a good idea using Handler, it runs in the UI thread with many other things to do in the queue, so that's not guarantee your runnable code would be executed so precisely.
If your work in the Runnable is just some logic task not involved in update UI.Consider using a Timer to do that but be ware that it will run on a separated thread.
What is the best way to delay a method call without freezing the UI or running of the program? I want to display circles on the screen every 5 seconds but in those 5 seconds, other existing circles will be changing size so the drawcircle method has to be called every 5 seconds but other code has to be able to run too.
Use Handler for it:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//any delayed code
}
}, 5000);
Causes the Runnable to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached. The time-base is in milliseconds, in eg above it is 5000 milliseconds.
The postDelayed takes two parameters:
The Runnable that will be executed.
The delay (in milliseconds) until the Runnable will be executed.
Use Handler's method called postDelayed.
For more info, read this.
So, there are multiple similar questions/answers about how to do a delay on Android. However they mostly focus on doing this on UI thread.
What if I need a delay in a worker thread in a service (and I don't want to put the thread to sleep)? the Handler.postDelayed() doesn't work as there is a "can't create a handler inside thread has not called Looper.prepare()" exception. CountDownTimer doesn't work for the same reason. And I don't have any views to call runOnUiThread().
So is the only solution to have a looper on each thread I have or there is another way to do this?
UPDATE:
It's silly, but I found the answer working for me in my own old code :).
Basically, if you want to start a Runnable with a delay from a non-UI thread, all you need to do is ask the main looper to handle this.
Handler handler = new Handler(Looper.getMainLooper());
Runnable r = new Runnable() {
#Override
public void run() {
// Do stuff to be run after a delay
// CAUTION: this won't be run on the same thread
}
};
handler.postDelayed(r, DELAY_TIME);
The drawback could be that the code in that Runnable will not be run on the same thread as the original code. This is why I'm not putting this approach as an answer to be accepted (I admit, the original question sounded like I want a timed event to happen on the same non-UI thread. For this I don't have an answer yet except the one from Emmanuel that I must attach a Looper to my thread). For my purposes however this works as I only need to start a service upon timeout.
Like you have seen from the Exceptions in order to use Handlers in a Thread you need to attach the Thread to the Looper. To give a bit more context, when you call postDelay() you are posting a message to the Thread's MessageQueue; the Looper is responsible for managing this Queue. So if you want to go the Handler route you will need to set up the Thread with a Looper.
If you want to delay the Thread without making it sleep() (I do not know why you cannot use sleep()) you can have a while that runs until a certain time from now has elapsed. (This sounds like a horrible idea).
I am a new Android developer. I am using the Handler class to schedule some operations. So I am creating runnable objects that calls some of my instance methods.
But I have a problem. Sometimes my run() method in Runnable object is called twice.
What could be the problem??
and there is the code
//deneme is a Handler.
deneme.postDelayed(new Runnable() {
#Override
public void run()
{
randomOyna();
//the instance method that I call.
}
}, 1000);
If don't schedule your Handler to run on another Thread than the UI-thread, there might be a hidden delay in the execution because your Runnable will also run on the UI-thread and thus will only be allowed to run when there is "time" for it. With this hidden delay, it might seem like it is run twice but in reality it's just and over-delayed running before a regular delayed Runnable.
Can't see a mistake just by looking the hint you gave us... But you might try plain old java to run threads instead of handler... Good luck...
Look here for more details