Обновление интерфейса из фонового потока во время сенсорного - PullRequest
2 голосов
/ 18 марта 2012

Я пытаюсь добавить наложение в MapView из фонового потока, чтобы оптически пометить точку, к которой в данный момент касается пользователь.

В данный момент я пытаюсь добиться этого, используя Timer / Handler. Когда MotionEvent имеет значение ACTION_DOWN, я публикую задачу, которая добавляет наложение кругов к наложениям mapView после определенной задержки.

К сожалению, пользовательский интерфейс обновляется только после того, как пользователь убирает палец с экрана (ACTION_UP).

Вот пример кода:

Пользовательский интерфейс

if (event.getAction() == MotionEvent.ACTION_DOWN) {
    handler = new OverlayHandler(mapView, centerDrawer) // centerDrawer is an overlay drawing a circle
    cTask = new DrawTimer(handler); // Calls handler.sendMessage, telling the handler to add centerDraw to the overlays of mapView

    handler.postDelayed(cTast, delay);

} else {
    handler.removeCallbacks(cTask);
}

Таймер (DrawTimer и т. Д.)

public void run() {
    Message msg = new Message();
    msg.what = 1;
    handler.sendMessage(msg);
}

Обработчик

public void handleMessage(Message msg) {
    switch (msg.what) {
    case 1:
            mapView.getOverlays().add(centerDrawer);
    break;
        // more cases
    }
    super.handleMessage(msg);
}

Насколько я знаю, это стандартный способ взаимодействия с пользовательским интерфейсом из фоновой задачи.

Это также верно для обновлений, когда пользователь взаимодействует с экраном? Должен ли я явно указывать представлению для визуализации новых наложений?

EDIT:

Код должен делать следующее: При касании он должен начать наблюдать, как долго пользователь продолжает касаться. После начальной задержки круг должен быть добавлен к виду. После еще одной задержки добавляется еще один оверлей и т. Д.

Я делаю это для каждого оверлея в два этапа: Я добавляю Runnable к обработчику, который будет выполнен после задержки. Затем Runnable отправляет соответствующее сообщение обработчику, сообщая ему, что рисовать. Я так делаю, потому что ...

  • Мне нужно иметь возможность отменить таймер (сообщение), если пользователь перемещает или отпускает палец.
  • Некоторые пометки должны меняться, когда пользователь продолжает касаться экрана. PostDelayed Runnable просто продолжает отправлять сообщения до отмены.

Вот почему я не просто использую отложенные сообщения.

Варианты использования

  • Пользователь касается экрана -> пользовательские выпуски до того, как проходит задержка (ничего не должно появляться)

  • Касание -> задержка прохождения -> круг -> отпускание

  • Касание -> задержка проходит -> кружок -> задержка 2 прохода -> кружок 2 -> отпускание

Ответы [ 2 ]

2 голосов
/ 18 марта 2012

в вашем комментарии написано "вызывает handler.sendMessage ...", но затем вы впоследствии отправляете сообщение в обработчик с задержкой.вы либо хотите вызвать sendMessage, либо postDelayed, но не оба одновременно.Вы помещаете сообщение в очередь 2 раза.Это не обязательно объясняет вашу проблему.

Вы должны опубликовать код DelayTimer и проверить значение задержки.

0 голосов
/ 20 марта 2012

Нашел ответ в этом вопросе: Представления не обновляются до тех пор, пока MapView не коснется

mapView.invalidate () заставляет представление перерисовывать все свои наложения.Возможно, это не самый эффективный способ реализации этого поведения, но он работает так, как я хочу.

Спасибо farble1670 за указание на некоторые проблемы с моей предыдущей реализацией.Следуя его совету, я изменил его, чтобы использовать только сообщения (которые также можно отменить с помощью removeMessage).

Новый код еще проще:

Поток пользовательского интерфейса

if (event.getAction() == MotionEvent.ACTION_DOWN) {
    handler = new OverlayHandler(mapView, centerDrawer)

    handler.sendEmptyMessageDelayed(1, d);

} else {
    handler.removeMessage(1);
}

Обработчик

public void handleMessage(Message msg) {
    switch (msg.what) {
    case 1:
        mapView.getOverlays().add(centerDrawer);
    break;
        // more cases
    }
    mapView.invalidate(); // Forces redrawing of all overlays
    super.handleMessage(msg);
}
...