Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.
8. Cargando datos
Lo que vas a aprender: buscar datos sin trabar la UI y mostrar listas grandes con eficiencia. Prerrequisitos: Gestionando el estado.
Ejemplo completo (copiar, pegar y ejecutar)
Carga los datos en un Thread de fondo, vuelve a la paint thread con Component.onUI y los muestra en una lista
virtualizada (VirtualListView + DataAdapter) que recicla views. Compila tal cual.
package com.exemplo;
import java.util.*;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
public class MainWindow extends Window
{
private final List<Tarefa> tarefas = new ArrayList<>();
private VirtualListView lista;
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
lista = new VirtualListView(Relative.ofFont(3f), new DataAdapter()
{
public int getCount() { return tarefas.size(); }
public Component createView() { return new Label(""); } // crea una vez
public void bindView(Component v, int i) { ((Label) v).setText(tarefas.get(i).titulo); }
});
add(LAY_FILL, lista);
carregar();
}
private void carregar()
{
new Thread(() -> {
var dados = listarDoRepositorio(); // trabajo pesado, thread de fondo
Component.onUI(() -> { // vuelve al paint thread
tarefas.clear();
tarefas.addAll(dados);
lista.notifyDataChanged(); // actualiza la lista virtualizada
});
}).start();
}
private List<Tarefa> listarDoRepositorio() // simula I/O
{
List<Tarefa> out = new ArrayList<>();
for (int i = 1; i <= 500; i++) out.add(new Tarefa("Tarefa " + i));
return out;
}
}
class Tarefa
{
final String titulo;
Tarefa(String titulo) { this.titulo = titulo; }
}
Los fragmentos de abajo muestran solo el núcleo (lo que va dentro de
onShow()). Para ejecutar, colócalos en el esqueletoMainWindowde arriba.
Por qué el I/O nunca ocurre en la paint thread
La UI corre en un solo thread — cualquier bloqueo en él congela la pantalla. El patrón obligatorio:
new Thread(() -> {
var dados = repo.listar(); // trabajo pesado, thread de fondo
Component.onUI(() -> { // vuelve al paint thread
vm.tarefas = dados;
lista.notifyDataChanged(); // actualiza la lista virtualizada
});
}).start();
Para reaccionar a un evento de UI que ya está en background, usa onActionThread (ver
Manejando la entrada).
Listas grandes: VirtualListView + DataAdapter
VirtualListView recicla views — renderiza solo lo visible. El adapter separa crear (una vez) de
vincular (barato, muchas veces):
VirtualListView lista = new VirtualListView(Relative.ofFont(3f), new DataAdapter() {
public int getCount() { return vm.tarefas.size(); }
public Component createView() throws Exception { return new CardTarefa(); }
public void bindView(Component v, int i) throws Exception { ((CardTarefa) v).bind(vm.tarefas.get(i)); }
});
add(LAY_FILL, lista);
// cuando los datos cambian:
lista.notifyDataChanged();
bindViewcorre mucho en el scroll — mantenlo barato e idempotente (nada de I/O ahí).
Construyes en este paso
La lista pasa a cargar en background y a renderizar virtualizada (usando el CardTarefa del
capítulo 3).
Recapitulando
I/O en Thread → Component.onUI; listas grandes con VirtualListView (reciclaje vía
createView/bindView); notifyDataChanged() al cambiar los datos.