【问题标题】:Optimal method for posponing onEvent?推迟onEvent的最佳方法?
【发布时间】:2012-04-14 07:28:18
【问题描述】:

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

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

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

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

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

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

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

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

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

【问题讨论】:

标签: android android-asynctask android-event


【解决方案1】:

我会这样做:

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

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

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

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

【讨论】:

    【解决方案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() 不会创建新线程,它只是将Runnable 添加到View 的线程队列中

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

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

    【讨论】:

      【解决方案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 提供了很好的示例。

      【讨论】:

      • +1 用于介绍 CountDownLatch。我认为我实际上可能会采用这种特殊的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多