Рабочий поток не может обновить пользовательский интерфейс на Motorola V3

Я работаю над приложением J2ME, которое должно быть перенесено на телефоны разных производителей. Пока приложение работает нормально, за исключением Motorola V3 (это единственный телефон Motorola, который я пробовал).

Проблема в том, что когда я запускаю новый поток и когда поток пытается обновить графику (вызывая repaint ()), графическая система становится стеком.

Некоторая полезная информация: - Я получаю отображение в конструкторе мидлета и повторно использую его в течение жизненного цикла приложения. - Есть только один класс, расширяющий Canvas. Здесь происходит каждый розыгрыш. Когда мне нужно перерисовать графику, я вызываю метод repaint () либо из потока пользовательского интерфейса, либо из другого потока Worker. Насколько мне известно, каждый поток может без проблем получить доступ к пользовательскому интерфейсу. - Я попробовал исправить, в котором в начале приложения я беру имя запущенного (UI) потока и сохраняю его для дальнейшего использования. Перед вызовом repaint () я проверяю, совпадает ли имя текущего потока с именем потока пользовательского интерфейса. Если одес, то делаю repaint(), иначе:

display.callSerially(new Runnable() {
    public void run() {
        repaint();
    }
});

Не могли бы вы указать мне на какие-либо особенности реализации J2ME в Motorola? Как я могу решить эту проблему с потоками, обновляющими пользовательский интерфейс?

Спасибо, Златко


person Bart    schedule 24.01.2011    source источник


Ответы (1)


В отличие от Swing, API-интерфейсы пользовательского интерфейса MIDP являются потокобезопасными. Это означает, что вам не нужно использовать callSerially для принудительного запуска вещей в потоке пользовательского интерфейса. Есть сообщения, что callSerially не работает на некоторых устройствах Motorola, поэтому лучше всего просто вызвать перерисовку самостоятельно.

Обратите внимание, что перекраска - это просто предложение системе произвести перекраску. Если вы хотите, чтобы перерисовка выполнялась немедленно, вы должны вызвать метод serviceRepaints.

Хорошее обсуждение обработки событий пользовательского интерфейса MIDP можно найти здесь.

person Eric Giguere    schedule 25.01.2011
comment
Спасибо за ваш ответ. Мой первоначальный подход заключался в прямом обновлении пользовательского интерфейса из рабочего потока, как вы предлагаете, с учетом упомянутой вами спецификации. Это не сработало. Это побудило меня искать другие решения (в том числе и то, что я написал в своем посте). - person Bart; 25.01.2011
comment
Чтобы сделать мой вариант использования более понятным: при запуске приложения отображается изображение в качестве заставки. В этот момент я создаю новый поток, который ждет 5 секунд, затем меняет изображение, которое должно использоваться методом paint (), и вызывает repaint (). Однако второе изображение никогда не появляется, а появляется первое (всплеск). Похоже, что repaint () не выполняется во второй раз или блокируется (этот код отлично работает на многих других устройствах). Любые идеи? - person Bart; 25.01.2011
comment
Возможно, поток событий заблокирован. Вы можете показать нам код? - person Eric Giguere; 25.01.2011
comment
Пожалуйста, взгляните на следующий URL-адрес для форматированного и синтаксического кода: copypastecode.com/62605 Это адаптированная версия кода для демонстрации концепции, хотя реальный код более сложен. Если что-то непонятно, с радостью объясню. - person Bart; 26.01.2011
comment
Теперь я не понимаю, зачем вы создали этот класс CanvasManager. Это похоже на то, что вы пытаетесь управлять экранами самостоятельно, вместо того, чтобы позволять это делать системе. Я бы избавился от этого материала и просто использовал бы обычные методы Display, чтобы нажимать и открывать экраны. Для экрана-заставки используйте Canvas, но запустите поток таймера в методе showNotify (). Затем поток таймера просто устанавливает отображение на соответствующий экран, когда время истекло. - person Eric Giguere; 26.01.2011
comment
Есть причина, по которой я не вызываю display.setCurrent (...) для каждого экрана, который мне нужен в приложении. На телефонах Nokia (особенно N95) это приводит к появлению белого экрана в течение нескольких миллисекунд между переходами между экранами, и это заметно. Однако я не делаю ничего необычного в CanvasManager, только беру новый экран и повторно использую тот же Displayable с его методом рисования. Насколько я знаю, showNotify () будет вызываться только при использовании вызова display.setCurrent (), верно? - person Bart; 26.01.2011
comment
Ах, ладно, понятно, было интересно. Что ж, я не вижу ничего явно неправильного, так что это, вероятно, какая-то ошибка. Вы все равно можете попробовать переместить таймер в showNotify, который будет вызываться непосредственно перед тем, как холст будет показан. Затем в потоке таймера попробуйте вызвать serviceRepaints () сразу после вызова repaint (). - person Eric Giguere; 26.01.2011