推迟事件的最佳方法?

时间:2012-03-30 15:22:38

标签: android android-asynctask android-event

在我的小应用程序中,我从系统(不受我控制)收到一系列排队的onEventXXX()。

无法保证onEventXXX()的时间安排。唯一可以肯定的是,它们是以顺序收到的,并将它们放入队列中。

在onEventXXX()内部,我必须触发一个操作(O),无法在另一个进程(P)进行时启动。

但我不能放弃这个"解雇手术(O)"。我必须等到那个过程(P)完成,然后解雇它。

IOW,我必须排队或至少推迟"解雇手术"直到该过程(P)完成。

我实现这一点的直接想法是,不是触发操作(O),我会:

  1. 启动一次性定时器,定期检查过程(P)
  2. 当计时器过去时,如果过程(P)没有完成,再次开始时间(本身)。
  3. 当计时器过去时,如果过程(P)完成,则开火操作(O)。
  4. 但是知道Android的丰富性,我怀疑有一种更好的方法可以做到这一点,已经内置到系统/ API中。

    如果有更好的方法来实现上述目标,它会是什么?

3 个答案:

答案 0 :(得分:3)

我会这样做:

    在onEventX中
  • ,检查进程是否退出,如果是,立即执行您的操作(您也可以省略此步骤并执行第2步)

  • 否则,创建AsyncTask,在doInBackground中调用Process.waitfor(),完成后,在onPostExecute中执行操作

使用这种方法,您可以尽快在UI线程上调用操作。

请勿使用计时器执行此任务。计时器是一种“轮询”方法。如果你的计时器滴答太快,你只会浪费CPU时间。如果它的速度太快,你的行动可能会被推迟。

答案 1 :(得分:3)

CountDownLatch将是最佳解决方案。

我没有详细的例子,但我认为你可以轻松使用它。

流程如下所示

  1. 定义CountDownLatch varaiable命名为latch
  2. 将锁存计数设置为1
  3. 当收到事件O时,制作一个新的ThreadO。在ThreadO中,等到锁存器的计数达到0。
  4. 当进程P完成时,倒计时锁定。
  5. 如果你这样编码,你可以轻松处理很多情况。

    1. 如果先收到O,您可以等到P完成。
    2. 如果P先收到,你可以立即开始。
    3. 您可以使用CountDownLatch提供的超时功能。
    4. 我在asyc单元测试中使用CountDownLatch。您可以在此处查看我的代码:http://kingori.egloos.com/4554640

      虽然它不像你的情况,但你可以从我的代码中获取提示。此外,CountDownLatch的javadoc提供了很好的示例。

答案 2 :(得分:2)

首先,我建议如果用户点击某些东西,他应该看到一些直接的结果,在你的情况下,如果按钮动作需要等待某事,立即在按钮上添加一个圆圈加载动画,向用户发出信号行动很快就会发生。

现在为行动本身, 如果在一个(或几个)可能的后台进程之后只有一个(或几个)这样的可能行为, 我将按钮同步引发一个标志(可能通过一个持久的类成员)并让长进程同步在完成它的进程并执行请求后检查该标志完成行动。

另一种可能的选择,如果使用wait和notify让按钮代码等待进程完成,这通常被认为是Java中非常高性能的解决方案:

例如

(忽略拼写错误,这是现场的):

button.setOnClickListener(new OnClickListener() { 
    public void onClick(View v) {
        v.post(new Runnable() {
            @Override
            public void run() {
                synchronized (lockObject) {
                    try {
                        lockObject.wait();
                        doAction();
                    } catch (InterruptedException e) {}
                }
            }
        }
    }
}

然后在完成时有一个很长的进程notify

请注意,new Runnable()不创建新线程,只是将Runnable添加到View的线程队列

正如鼠标所建议的那样,按钮onClick处理程序应检查进程当前是否正在运行,如果是,则立即执行操作。

这样您就不需要创建新线程(或实际上是线程池的AsyncTask)