Взаимодействие с потоками пользовательского интерфейса в Java / J2ME

Пишу приложение J2ME. Одна из частей - это то, что периодически опрашивает содержимое каталога и, если есть какие-то новые вещи, рисует их на экране. Я сделал это, заставив UI-форму запустить поток опроса с указателем обратно на себя, и когда поток опроса находит что-то, он обращается обратно к форме и вызывает синхронизированный метод для обновления его отображения. Кажется, это нормально работает.

У меня такой вопрос. В C # /. NET я знаю, что нежелательно, чтобы потоки, не относящиеся к пользовательскому интерфейсу, обновляли пользовательский интерфейс, и правильный способ справиться с этим - делегировать это потоку пользовательского интерфейса.

Например. следующее:

public void DoSomeUIThing()
{
    if (this.uiComponent.InvokeRequired)
    {
        this.uiComponent.Invoke(someDelegateThatCallsBackToThis);
    }
    else
    {
        this.uiComponent.Text = "This is the update I want to happen";
    }
}

Есть ли эквивалент J2ME для управления этим процессом? А как насчет Java? Или Java / J2ME просто лучше в этом отношении? Если нет, то как это сделать?

[EDIT] Похоже, что Swing поддерживает то, о чем я спрашиваю, с помощью методов SwingUtilities.invokeLater () и invokeAndWait (). Есть ли эквивалентный фреймворк для J2ME?


person Cory    schedule 15.11.2008    source источник
comment
Только что завершил свой ответ с конкретной информацией J2ME   -  person VonC    schedule 15.11.2008
comment
Спасибо! Мое приложение - LCDUI, поэтому, думаю, мне не о чем беспокоиться (по крайней мере, если я верю Дэвиду Пирсу).   -  person Cory    schedule 15.11.2008


Ответы (5)


Что касается Java, то то, что вы описываете, выглядит как SwingWorker (рабочий поток ).

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

Программа Swing включает следующие типы потоков:

  • Начальные потоки, потоки, которые выполняют исходный код приложения.
  • Поток отправки событий, в котором выполняется весь код обработки событий. Большая часть кода, взаимодействующего со структурой Swing, также должна выполняться в этом потоке.
  • Рабочие потоки, также известные как фоновые потоки, в которых выполняются длительные фоновые задачи.

Правило одного потока:
Однажды Компонент Swing реализован, весь код, который может влиять на состояние этого компонента или зависеть от него, должен выполняться в потоке диспетчеризации событий.

При использовании в контексте J2EE необходимо соблюдать осторожность при ссылках SwingWorker из EJB.

Что касается J2ME, это зависит от того, являетесь ли вы разработка вашего приложения как стандартного мидлета, который будет работать на любом устройстве с поддержкой MIDP, или например как RIMlet, приложение на основе CLDC, которое использует специфичные для BlackBerry API-интерфейсы и, следовательно, будет работать только на устройствах BlackBerry .

Поскольку в отличие от классов пользовательского интерфейса MIDP, RIM похожи на Swing в том смысле, что операции пользовательского интерфейса происходят в потоке событий, который не является потокобезопасным, как в MIDP. Чтобы запустить код в потоке событий, приложение должно получить блокировку объекта события или использовать invokeLater () или invokeAndWait () - дополнительная работа для разработчика, но за изысканность приходится платить.

Но для LCDUI вы можете доступ к форме из нескольких потоков .

person VonC    schedule 15.11.2008
comment
Смотрите редактирование - ссылка на правило однопоточного правила описывает, как это сделать для свинга. Вы знаете что-нибудь подобное в J2ME? - person Cory; 15.11.2008

Есть много профилей Java ME. Если вы имеете в виду MIDP, то Display.runSerially - это то, что вам нужно.

Для AWT (Swing) вы должны использовать EventQueue.invokeLater (SwingUtilities.invokeLater необходимо только потому, что Java 1.1 не имеет метода EventQueue - 1.2 собирается отпраздновать свой десятый день рождения). Для Common DOM API используйте DOMService.invokeLater.

Независимо от того, какие утверждения GUI API могут делать о потокобезопасности, они, вероятно, ошибочны (некоторые утверждения Swing удалены в JDK7, потому что они нереализуемы). В любом случае код приложения вряд ли будет потокобезопасным.

person Tom Hawtin - tackline    schedule 15.11.2008

Для приложений j2me вы, вероятно, захотите сделать это простым. Главное, касаться UI-компонентов только в потоке событий. Прямой способ сделать это - использовать invokeLater. или invokeAndWait. В зависимости от ваших библиотек у вас не будет доступа ни к чему, кроме этого. В общем, если они не предусмотрены на вашей платформе, это, вероятно, означает отсутствие поддержки потоков и отсутствие проблем. Например, Blackberry поддерживает это.

person carson    schedule 15.11.2008

Если вы разрабатываете под SWT, это выполняется с помощью метода asyncExec () объекта Display. Вы передаете объект, реализующий Runnable, чтобы поток пользовательского интерфейса выполнял изменения, сделанные в другом потоке.

Это пример, заимствованный из здесь

public void itemRemoved(final ModelEvent me)
{
   final TableViewer tableViewer = this.viewer;

   if (tableViewer != null)
   {
      display.asyncExec(new Runnable()
      {
         public void run()
         {
            tableViewer.remove(me.getItem());
         }
      }
   }
}
person Fernando Miguélez    schedule 15.11.2008

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

person Community    schedule 23.04.2010