【问题标题】:How can I do non-blocking events processing on Android?如何在 Android 上进行非阻塞事件处理?
【发布时间】:2011-06-27 00:39:09
【问题描述】:

这个问题是关于 Android 上的事件处理。它不是特定于 c++ 的。

我需要处理 UI/OS 事件,而不是在处理完所有事件后阻塞。

原因是我要移植的应用程序非常大,不能轻易地重写以在工作线程上处理它自己的东西。相反,应用程序引擎要求在冗长的操作期间处理 UI/OS 事件,否则这些操作会阻塞。

我发现 ALooper_pollAll(...) 不适合我。例如,如果我在我的活动中创建一个对话框并开始一个长操作,ALooper_pollAll() 不会让我的对话框出现 - 它只会在我返回主循环时显示(我在 onNativeWindowCreated 中对此进行了测试)。

我发现几乎可行的唯一解决方案是在 UI 线程上执行内部循环,通过 JNI 调用以下代码:

public class MyActivity extends NativeActivity {

  private Handler _uiEventsHandler = null;

  private Runnable _uiEventsTask = new Runnable() {
    public void run() {
      Looper looper = Looper.myLooper();
      looper.quit();
      _uiEventsHandler.removeCallbacks(this);    
      _uiEventsHandler = null;
    }
  };

  public void ProcessEvents(int timeout)
  {
    if (_uiEventsHandler==null) {
      Looper looper = Looper.myLooper();
      _uiEventsHandler = new Handler(looper);
      _uiEventsHandler.removeCallbacks(_uiEventsTask);    
      //_uiEventsHandler.postDelayed(_uiEventsTask,timeout);    
      _uiEventsHandler.post(_uiEventsTask);    
      try {
        looper.loop();
      } catch (RuntimeException re) { 
        // We get an exception when we try to quit the loop, but the inner loop actually terminates
      }
    }
  }
}

然而,这不是一个最佳解决方案,因为它不会循环,直到没有更多事件要处理(因为可能在循环运行期间创建事件)。

在我的研究过程中,我发现我可以从 Looper 中获取 MessageQueue 并添加一个可以退出我的内部循环的 IdleHandler。我还没有尝试过,一定有更好的方法。

鉴于这是我必须坚持的架构,有什么更好的解决方案?

更新:

使用 MessageQueue 我能够实现我所需要的:

public class MyActivity extends NativeActivity {

  private class IdleHandler implements MessageQueue.IdleHandler {
    private Looper _looper;
    protected IdleHandler(Looper looper) {
      _looper = looper;
    }
    public boolean queueIdle() {
      _uiEventsHandler = new Handler(_looper);
      _uiEventsHandler.post(_uiEventsTask);    
      return(false);
    }
  };

  private boolean _processingEventsf = false;
  private Handler _uiEventsHandler = null;

  private Runnable _uiEventsTask = new Runnable() {
    public void run() {
      Looper looper = Looper.myLooper();
      looper.quit();
      _uiEventsHandler.removeCallbacks(this);    
      _uiEventsHandler = null;
    }
  };

  public void ProcessEvents()
  {
    if (!_processingEventsf) {
      Looper looper = Looper.myLooper();
      looper.myQueue().addIdleHandler(new IdleHandler(looper));
      _processingEventsf = true;
      try {
        looper.loop();
      } catch (RuntimeException re) { 
        // We get an exception when we try to quit the loop.
      }
      _processingEventsf = false;
    }
  }
}

不过,我还是想知道是否有更好的解决方案。

【问题讨论】:

  • 哇。 :) 我对其中的大部分内容都不太了解(2-3 周前才开始研究 Android),但我当然可以感觉到,迟早我自己也会需要这些东西,所以我很快就喜欢上了它。 :) 谢谢!

标签: android events java-native-interface message-queue looper


【解决方案1】:

不确定我是否正确理解了这个问题,但您是否尝试过使用 IntentService?

http://developer.android.com/reference/android/app/IntentService.html

来自文档:

这种“工作队列处理器”模式通常用于从应用程序的主线程卸载任务。 IntentService 类的存在是为了简化这种模式并处理机制。”

【讨论】:

  • 这不是我需要做的,我需要在主线程上工作,并手动控制事件处理何时发生以及持续多长时间。
猜你喜欢
  • 2019-11-16
  • 1970-01-01
  • 2010-12-08
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多