Взаимодействие с потоками пользовательского интерфейса в Java / J2ME - PullRequest
5 голосов
/ 15 ноября 2008

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

У меня вопрос такой. В 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?

Ответы [ 5 ]

5 голосов
/ 15 ноября 2008

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

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

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

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

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

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

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

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

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

4 голосов
/ 15 ноября 2008

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

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

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

1 голос
/ 23 апреля 2010

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

1 голос
/ 15 ноября 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());
         }
      }
   }
}
1 голос
/ 15 ноября 2008

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

...