Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

Background work

This page consolidates the threading pattern that appears in all the previous ones, from the point of view of whoever writes the heavy work. The “why” is in The paint thread.

The canonical template

new Thread(() -> {
   var resultado = trabalhoPesado();        // I/O or CPU — NEVER on the paint thread
   meuComponente.onUI(() -> {               // re-enters the paint thread
      mostrar(resultado);                    // touch the UI only here
      Component.repaint();
   });
}).start();

Ways to re-enter the UI:

Call Use
Component.onUI(Runnable) from any thread, starting from a component
Main.runOnPaintThread(Runnable) same, outside the context of a component
Main.runOnPaintThreadAndWait(Runnable) same, blocking until it finishes

React to a UI event on a thread

When a component’s handler must run heavy work, use onActionThread (runs off the paint thread) and re-enter with onUI:

botao.onActionThread(c -> {
   var dados = baixar();                    // off the paint thread
   c.onUI(() -> lista.setItems(dados));     // back to the UI
});

Timers

For periodic work (polling, watchdog), use the framework timers:

comp.addTimer(1000);   // fires a timer event every 1000 ms (handled in the component)

util utilities

  • ThreadSync — a 2-thread barrier (producer/consumer): start()/start(maxMillis), finished(resultado), getResult(). Useful for waiting on a result from another thread with a timeout.
  • RunnableWith<T> — callback with an argument: void run(T obj). It is the type of the callbacks that deliver a value (e.g., onError of GPSThread).
ThreadSync sync = new ThreadSync();
new Thread(() -> { var r = calcular(); sync.finished(r); }).start();
sync.start(5000);                 // waits up to 5 s
Object r = sync.getResult();

Best practices

  • All blocking I/O (DB, HTTP, GPS, BLE) runs off the paint thread.
  • Touch the UI only inside onUI(...)/runOnPaintThread(...).
  • Stop threads/timers when leaving the screen (in onRemove()), otherwise they leak.

Common mistakes

  • Touching widgets from a Thread without onUI(...) → erratic behavior/freeze.
  • runOnPaintThreadAndWait(...) called from inside the paint thread (deadlock) — use the non-blocking variant there.
  • Timers/threads not cancelled when switching screens.

See also

Was this page helpful?