5

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

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

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

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

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

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

但是,我仍然想知道是否有更好的解决方案。

4

1 回答 1

0

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

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

从文档:

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

于 2012-04-02T00:08:32.963 回答