6

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

不能保证那些 onEventXXX() 的时间。唯一可以保证的是,它们按照它们被放入队列的顺序被接收。

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

但是我不能仅仅放弃这个“触发操作(O)”。我必须等到该过程(P)完成,然后触发它。

IOW,我必须排队或至少推迟“触发操作”,直到该过程(P)完成。

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

  1. 启动一个一次性计时器,定期检查进程 (P)
  2. 当计时器过去时,如果进程 (P) 未完成,则重新开始计时(本身)。
  3. 当计时器经过时,如果过程 (P) 完成,则触发操作 (O)。

但是知道 Android 的丰富性,我怀疑有更好的方法来做到这一点,已经内置到系统/API 中。

如果有更好的方法来实现上述内容,那会是什么?

4

3 回答 3

3

我会这样做:

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

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

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

不要为此任务使用计时器。定时器是一种“轮询”方法。如果您的计时器计时太快,您只会浪费 CPU 时间。如果滴答声太慢,您的操作可能会延迟调用。

于 2012-04-02T06:33:57.990 回答
3

CountDownLatch将是最好的解决方案。

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

过程如下

  1. 定义名为锁存器的 CountDownLatch 变量
  2. 将锁存器计数设置为 1
  3. 当收到事件 O 时,创建一个新的 ThreadO。在 ThreadO 中,等待闩锁的计数达到 0。
  4. 当进程 P 完成时,倒计时锁存。

如果你这样编码,你可以轻松处理许多情况。

  1. 如果 O 先收到,则可以等到 P 完成。
  2. 如果 P 先收到,您可以立即启动 O。
  3. 您可以使用 CountDownLatch 提供的超时功能。

我在 asyc 单元测试中使用 CountDownLatch。你可以在这里看到我的代码:http: //kingori.egloos.com/4554640

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

于 2012-04-06T05:45:21.103 回答
2

首先,我建议如果用户单击某物,他应该会立即看到一些结果,在您的情况下,如果按钮操作需要等待某物,请立即在按钮上添加一个圆形加载动画,以向用户发出该操作将发生的信号不久。

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

另一种可能的选择是使用等待和通知让按钮代码等待进程完成,这通常被认为是 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()它不会创建新线程,它只是将 a 添加RunnableView的线程队列中

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

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

于 2012-04-05T08:40:41.030 回答