这个问题是关于 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;
}
}
}
但是,我仍然想知道是否有更好的解决方案。