Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

Performance e listas grandes

Como manter 60 fps — inclusive em GPU low-end — com muitos dados ou desenho pesado. O “porquê” (paint thread única, render sob demanda) está em A paint thread e O pipeline de renderização.

Virtualize: VirtualListView, não ListView

ListView mantém todos os itens em memória. Para centenas/milhares, use VirtualListView — ele recicla views (renderiza só o visível). O adapter separa criar (uma vez, reciclado) de vincular (barato, roda muito):

VirtualListView lista = new VirtualListView(Relative.ofFont(3f), new DataAdapter() {
   public int getCount() { return dados.size(); }
   public Component createView() throws Exception {         // criado poucas vezes (pool)
      return new Label("");
   }
   public void bindView(Component v, int i) throws Exception {  // roda MUITO no scroll → barato e idempotente
      ((Label) v).setText(dados.get(i).nome);
   }
});
// ao mudar os dados:
lista.notifyDataChanged();

bindView deve ser barato e idempotente — ele roda a cada reciclagem no scroll. Nada de I/O, alocação ou cálculo caro ali.

Por quê reciclar: o custo real é createView(). Reciclando, a memória fica constante independentemente de getCount() — 10 ou 10.000 itens usam o mesmo punhado de views.

Paginação remota: PagedDataAdapter

Para dados que vêm por página (rede), use PagedDataAdapter (cache LRU interno):

var adapter = new PagedDataAdapter(50, 4) {   // 50 itens/página, 4 páginas em cache
   public int getTotalCount() { return total; }
   public void loadPage(int page, PageCallback cb) {
      new Thread(() -> {
         Object[] itens = api.buscarPagina(page, pageSize);   // fora da paint thread
         Component.onUI(() -> cb.onPageLoaded(page, itens));   // volta à UI
      }).start();
   }
   public Component createView() throws Exception { return new Label(""); }
   public void bindItem(Component v, Object item, int i) throws Exception {
      ((Label) v).setText(((Cliente) item).nome);
   }
};

Desenho: onPaint barato e render sob demanda

  • Não repinte por frame. Chame repaint() só quando o estado muda — a tela não redesenha sozinha (render sob demanda).
  • Não aloque em onPaint. Ele roda para a árvore inteira a cada frame; reuse objetos (GRect, Font) em campos, não crie por frame.
  • Nunca bloqueie a paint thread — I/O de banco/rede em thread de trabalho + onUI.

Boas práticas

  • VirtualListView a partir de ~centenas de itens; ListView só para listas pequenas/fixas.
  • bindView/bindItem enxutos; carregue imagens/dados fora e vincule o já-pronto.
  • Imagens grandes: redimensione uma vez (escala destrutiva) em vez de escalar por frame.

Erros comuns

  • ListView com milhares de itens (estoura memória / trava).
  • bindView fazendo I/O ou alocando (engasga o scroll).
  • Repintar em loop/por frame em vez de sob demanda.

Veja também

Esta página foi útil?