Android上的延迟事件

我正在编写一个Android应用程序,安排某些方法以不规则的时间间隔触发。 据我所知,至less有两种方法可以做到这一点:

  1. 使用Handler.postDelayed在给定时间后执行Runnable

  2. 在给定的时间之后,使用Timer来计划和执行TimerTask

我正在寻找一个解决scheme,可以处理多个事件快速连发。 哪个是最好的方法? 有没有更好的我失踪?

Solutions Collecting From Web of "Android上的延迟事件"

简短的回答

他们在后台工作的方式不同,使用错误的方式会产生可怕的后果。

发送到处理程序的所有消息和可运行程序与创build处理程序的线程(通常是服务或活动线程)运行在同一个线程上。

计时器另一方面产生一个新的线程。

听起来像定时器是给你的方式,但它是不可能肯定地说出所给的信息。
这一切都归结为如果你想要在一个线程或多个线程上运行一切,都有其优点和缺点。

长答案

处理程序

从处理程序文档 :

每个Handler实例都与单个线程和该线程的消息队列相关联。 当你创build一个新的Handler时,它绑定到正在创build它的线程的线程/消息队列 – 从这一点开始,它将消息和可运行消息传递到消息队列,并在消息出来时执行它们队列。

这意味着只有一个事件可以与处理程序同时处理,并且所有其他消息/可运行程序需要等待另一个消息正在执行。
然而,处理程序是唯一的方法去如果你想操纵用户界面,因为只有主UI线程被允许这样做。

如果您不小心,使用处理程序可能会导致应用程序冻结。
一个常见的错误是,当人们在主UI线程上创build一个处理程序,产生一堆工作线程并使用处理程序调用沉重的方法时,这将导致主UI线程locking,并使可怕的“应用程序没有响应”在android中的对话框

这样的处理程序可以很好地处理线程安全性,您可以使每个线程都有一个处理所有跨线程调用(使用消息)的处理程序,如果确保只有处理程序修改了一个对象,则永远不会出现线程问题。

计时器

但是,使用定时器会导致开销或创build线程以及线程增加的复杂性, 所以在修改共享对象时要小心!

优点是并发性,如果需要同时运行多个任务(或者在很短的时间间隔内),处理程序可能无法处理它,而计时器将会处理它。

其他选项

  • 您可能可以使用DelayQueue
  • 如果您想允许手机进入睡眠状态并有较长的延迟时间,请使用AlarmManager

我使用Timer来延迟事件进程,在延迟期间,较新的来临事件将覆盖较旧的事件。 因此,当用户input文本足够快时,onTextChanged事件将不会被处理太多次。

 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) { } });