Delayed Events on Android
I'm writing an Android app that schedules certain methods to fire at irregular intervals. As far as I know, there are at least two ways to do this:
use
Handler.postDelayed
to execute aRunnable
after a given time.use a
Timer
to schedule and execute aTimerTask
a开发者_Python百科fter a given time.
I'm looking for a solution that can handle multiple events firing in quick succession. Which is the best method to use? Is there a better one I'm missing?
Short answer
The differ in how they work in the background, using the wrong one can have dire consequences.
All messages and runnables sent to a handler is run on the same thread as the one that created the handler, often a service or activity thread.
Timer on the other hand spawns a new thread.
Sounds to me like Timer is the way to go for you but it is impossible to say for sure with the information given.
It all boils down to if you want everything to be run on one thread or multiple threads, both has it's advantages and disadvantages.
Long answer
Handlers
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.
This means that only one event can be handled simultaneously with the handler and all other messages/runnables need to wait while another one is executing.
Handler is however the only way to go if you want to manipulate the UI as only the main UI thread is allowed to do so.
Using handlers can result in your application freezing if you don't take care.
A common mistake is when people create a handler on the main UI thread, spawn a bunch of worker threads and call heavy methods using handlers, this will cause the main UI thread to lock up and will make the dreaded "The application is not responding" dialog in android
That said handlers can be great for dealing with thread safety, you can make every thread have a handler which handles all cross thread calls (using messages) and if you make sure only the handler modifies an object you will never have threading issues.
Timers
With timers however you get the overhead or creating threads and the added complexity of threading, be careful when modifying shared objects!
The advantage is concurrency, if multiple tasks needs to be run simultaneously (or in very short interval) handlers might not be able to handle it whereas timers will.
Other options
- You might be able to use
DelayQueue
- If you want to allow the phone to sleep and have longer delays use
AlarmManager
I used the Timer to delay the event process, during the delay period, the newer comming event will override the older one. So that the onTextChanged events will not be process too many times when user enter text quick enough.
EditText editor_
Timer editorTimer_
editor_.addTextChangedListener(new TextWatcher()
{
@Override
public void onTextChanged(final CharSequence s, int start, int before, int count)
{
try
{
/* events absorber technique */
if (editorTimer_!=null)
{
editorTimer_.cancel(); //dump the timer to cancel the previous onTextChange firing
}
//the timer is dumped, we must to create a new one
editorTimer_ = new Timer();
//schedule a task which will be executed in 500ms if the timer won't canceled due
//to other (possible future) onTextChanged event
editorTimer_.schedule(new TimerTask()
{
@Override
public void run()
{
try
{
/*
* do whatever onTextChanged event have to do. But it should be quick
* heavy process must be executed on other thread
*/
if (TextUtils.isEmpty(s))
{
...
}
else
{
...
}
}
catch (Exception ex)
{
Log.w(TAG, ex.toString());
}
}
}, 500); //the 500ms delay is here
}
catch (Exception ex)
{
Log.w(TAG, ex.toString());
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
{
}
@Override
public void afterTextChanged(Editable s)
{
}
});
精彩评论