Interagindo com encadeamentos de interface do usuário no Java / J2ME

Estou escrevendo um aplicativo J2ME. Uma das partes é algo que pesquisa o conteúdo de um diretório periodicamente e, se houver alguma novidade, as pinta na canvas. Eu fiz isso por ter o formulário de interface do usuário lançar um segmento de pesquisa com um ponteiro de volta para si mesmo e quando o thread de pesquisa localiza algo que chama de volta para o formulário e chama um método sincronizado para atualizar sua exibição. Isso parece funcionar bem.

A questão que tenho é essa. No c # / .net eu sei que não é bom ter threads não-interface do usuário atualizando a interface do usuário e a maneira correta de lidar com isso é delegá-lo até o segmento de interface do usuário.

Por exemplo, o seguinte:

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

Existe um equivalente J2ME para como gerenciar esse processo? Como sobre o Java? Ou o Java / J2ME é mais legal em relação a isso? Se não, como isso é feito?

[EDITAR] Parece que o Swing suporta o que eu estou perguntando através dos methods SwingUtilities.invokeLater () e invokeAndWait (). Existe uma estrutura equivalente para o J2ME?

Em relação ao Java, o que você está descrevendo parece um SwingWorker (thread de trabalho) .

Quando um programa Swing precisa executar uma tarefa de longa execução, ele geralmente usa um dos threads de trabalho, também conhecidos como threads de segundo plano.

Um programa Swing inclui os seguintes tipos de threads:

  • Threads iniciais, os threads que executam o código inicial do aplicativo.
  • O encadeamento de expedição de events, no qual todo o código de manipulação de events é executado. A maioria dos códigos que interagem com o framework Swing também devem ser executados neste thread.
  • Threads de trabalho, também conhecidos como threads de segundo plano, em que as tarefas em segundo plano que consomem tempo são executadas.

Regra de thread único :
Depois que um componente Swing é realizado, todo o código que pode afetar ou depender do estado desse componente deve ser executado no encadeamento de expedição de events.

Quando usado em um contexto J2EE, você precisa ter cuidado ao referenciar um SwingWorker a partir de um EJB .

Em relação ao J2ME , depende se você está desenvolvendo seu aplicativo como um MIDlet padrão que será executado em qualquer dispositivo habilitado para MIDP ou, por exemplo, como um RIMlet, um aplicativo baseado em CLDC que usa APIs específicas do BlackBerry e será executado somente no BlackBerry dispositivos.

Porque ao contrário das classs de interface do usuário do MIDP, os RIMs são semelhantes ao Swing no sentido de que as operações da interface do usuário ocorrem no thread de events, que não é thread-safe como no MIDP. Para executar código no encadeamento de events, um aplicativo deve obter um bloqueio no object de evento ou usar invokeLater () ou invokeAndWait () – trabalho extra para o desenvolvedor, mas a sofisticação vem com um preço.

Mas, para o LCDUI , você pode acessar um formulário a partir de vários segmentos .

Existem muitos perfis do Java ME. Se você quer dizer MIDP então Display.runSerially é o que você quer.

Para AWT (Swing) você usaria EventQueue.invokeLater ( SwingUtilities.invokeLater é necessário apenas porque o Java 1.1 não possui o método EventQueue – 1.2 está prestes a comemorar seu décimo aniversário). Para a API do DOM comum, use DOMService.invokeLater .

Não importa quais declarações uma API da GUI possa fazer sobre segurança de thread, elas provavelmente estão erradas (algumas das declarações do Swing são removidas no JDK7 porque elas não são implementáveis). Em qualquer caso, o código do aplicativo provavelmente não é thread-safe.

Para os aplicativos do j2me, você provavelmente quer mantê-lo simples. O principal é tocar componentes da interface do usuário apenas no encadeamento do evento. A maneira direta de fazer isso é usar invokeLater ou invokeAndWait . Dependendo de suas bibliotecas, você não terá access a mais do que isso. Em geral, se estes não são fornecidos em sua plataforma, provavelmente equivale a não haver suporte a threads e não ser um problema. Por exemplo, o BlackBerry suporta isso .

Se você desenvolver sob o SWT, isso será realizado por meio do método asyncExec () do object Display. Você passa um object implementando Runnable para que o thread da interface do usuário execute as alterações feitas em outro thread.

Este é um exemplo emprestado daqui

 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()); } } } } 

Eu posso atestar que o kit de ferramentas de interface do usuário do MIDP é de fato thread-safe, como eu tenho grandes MIDlets com GUI complexa em execução em milhões de telefones feitos por quase todos os fabricantes e nunca vi um problema a esse respeito.