Как я могу сделать неблокирующую обработку событий на Android? - PullRequest
5 голосов
/ 14 февраля 2011

Этот вопрос касается обработки событий на Android. Это не относится к c ++.

Мне нужно обрабатывать события UI / OS, без блокировки, когда все события были обработаны.

Причина в том, что приложение, которое я портирую, очень большое, и его нелегко переписать, чтобы оно работало с собственным материалом в рабочем потоке. Вместо этого ядро ​​приложения запрашивает события UI / OS для обработки во время многоплановых операций, которые в противном случае блокировали бы.

Я обнаружил, что ALooper_pollAll (...) не делает этого для меня. Если я, например, создаю диалог в своей деятельности и запускаю длинную операцию, ALooper_pollAll () не заставит мой диалог появиться - он будет отображаться только когда я вернусь в основной цикл (я проверял это в onNativeWindowCreated).

Единственное решение, которое я нашел почти работающим, - это выполнить внутренний цикл в потоке пользовательского интерфейса, вызвав следующий код через 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
      }
    }
  }
}

Это, однако, не оптимальное решение, потому что оно не будет зациклено, пока не будет больше событий для обработки (потому что события могут быть созданы во время выполнения цикла).

Во время моего исследования я обнаружил, что могу получить MessageQueue от Looper и добавить 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;
    }
  }
}

Однако я все еще хотел бы знать, есть ли лучшее решение.

1 Ответ

0 голосов
/ 02 апреля 2012

Не уверен, правильно ли я понял вопрос, но пытались ли вы использовать IntentService?

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

Из документов:

Этот шаблон «обработчик очереди работ» обычно используется для выгрузки задач из основного потока приложения. Класс IntentService существует, чтобы упростить этот шаблон и позаботиться о механике. "

...