Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.
PagedDataAdapter
PagedDataAdapter es un DataAdapter paginado para VirtualListView, con un caché LRU de páginas. Mantiene solo algunas páginas en memoria; al desplazarse a una región cuya página fue descartada, muestra un spinner y recarga asincrónicamente vía loadPage.
Es una clase abstracta: tú implementas getTotalCount, loadPage, createView y bindItem. La traducción índice→página, el caché, el spinner y el bloqueo de scroll durante la carga ya vienen listos.
🔴 · Paquete:
dev.crossfly.ui· Implementa:VirtualListView.DataAdapter· Uso: pasado al constructor deVirtualListView
Cuándo usar
- Datos que vienen de red/base de datos en páginas y no caben todos en memoria.
- Quieres caché automático (LRU) con recarga transparente al volver a una región antigua.
Cuándo NO usar
- Todos los datos ya están en memoria → implementa
DataAdapterdirectamente en elVirtualListView. - Lista pequeña →
ListView.
Ejemplo completo (copiar, pegar y ejecutar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Relative
/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
final int pageSize = 20;
final int total = 10_000;
PagedDataAdapter adapter = new PagedDataAdapter(pageSize, 5) { // 20 ítems/página, 5 páginas
public int getTotalCount() { return total; }
public void loadPage(int pageIndex, PageCallback cb) {
// Simula una carga (reemplace por llamada de red/base en background).
Object[] data = new Object[pageSize];
for (int i = 0; i < pageSize; i++)
data[i] = "Item " + (pageIndex * pageSize + i);
cb.onPageLoaded(pageIndex, data);
}
public Component createView() { return new Label(""); }
public void bindItem(Component view, Object item, int index) {
((Label) view).setText(item.toString());
}
};
VirtualListView list = new VirtualListView(Relative.ofFont(2f), adapter);
add(LAY_FILL, list); // las listas usan LAY_FILL (absorben la altura)
}
}
Los fragmentos de abajo muestran solo el núcleo (lo que va dentro de
onShow()). Para ejecutar, colócalos en el esqueletoMainWindowde arriba.
Uso básico
PagedDataAdapter adapter = new PagedDataAdapter(20, 5) { // 20 ítems/página, 5 páginas en memoria
public int getTotalCount() { return serverTotal; }
public void loadPage(int pageIndex, PageCallback cb) {
api.fetch(pageIndex, data -> cb.onPageLoaded(pageIndex, data)); // puede ser background
}
public Component createView() { return new Label(""); }
public void bindItem(Component view, Object item, int index) {
((Label) view).setText(item.toString());
}
};
VirtualListView list = new VirtualListView(Relative.ofFont(2f), adapter);
layout.add(LAY_FILL, list);
Constructores
| Constructor | Descripción |
|---|---|
PagedDataAdapter(int pageSize, int maxCachedPages) |
pageSize: ítems por página. maxCachedPages: páginas mantenidas en memoria (LRU) |
Ambos campos son public final. La VirtualListView se inyecta a sí misma en el adapter cuando pasas este adapter a su constructor.
Métodos abstractos a implementar
| Método | Descripción |
|---|---|
int getTotalCount() |
Total de ítems en el servidor (usado por getCount()) |
void loadPage(int pageIndex, PageCallback callback) |
Carga una página asíncrona; llama a callback.onPageLoaded(pageIndex, items) al terminar (desde cualquier thread) |
Component createView() throws Exception |
Crea una view en blanco |
void bindItem(Component view, Object item, int index) throws Exception |
Vincula el ítem crudo (Object) a la view — haz el cast a tu tipo |
Propiedades y métodos útiles
| Método | Tipo | Qué hace |
|---|---|---|
isAvailable(int index) |
boolean |
Si el ítem ya está en el caché |
clearCache() |
void |
Vacía caché y estado de carga |
getCount() |
int |
Delega a getTotalCount() |
Funcionamiento (resumen)
bindView(view, index)traducepageIndex = index / pageSizeeitemInPage = index % pageSize.- Página en el caché →
bindIteminmediato (waitingForData = false). - Página ausente →
waitingForData = truey dispararequestPage(pageIndex).
- Página en el caché →
requestPageevita solicitudes duplicadas (loading), muestra spinner y pausa el fling; al volver el callback, marshala a la thread de UI conComponent.onUI(...), graba la página, oculta el spinner, fuerza el re-bind de la franja (invalidateRange) y reanuda el fling.- El
cachees unLinkedHashMapen modo access-order que descarta la página más antigua (LRU) cuando excedemaxCachedPages.
Callbacks y eventos
| Callback | Cuándo se dispara |
|---|---|
PageCallback.onPageLoaded(int pageIndex, Object[] items) |
Tú lo llamas al terminar de cargar la página (desde cualquier thread) |
Estados
waitingForData—truemientras alguna página carga; señala a laVirtualListViewque bloquee el scroll.- LRU — las páginas antiguas se descartan; al desplazarse de vuelta, se recargan (nuevo spinner + solicitud).
Ejemplo — cast de ítem tipado
PagedDataAdapter adapter = new PagedDataAdapter(50, 4) {
public int getTotalCount() { return repo.total(); }
public void loadPage(int page, PageCallback cb) {
repo.loadAsync(page, 50, lista -> cb.onPageLoaded(page, lista.toArray()));
}
public Component createView() { return new Label(""); }
public void bindItem(Component view, Object item, int index) {
Cliente c = (Cliente) item; // cast del Object crudo
((Label) view).setText(c.getNome());
}
};
VirtualListView list = new VirtualListView(Relative.ofFont(2.4f), adapter);
Buenas prácticas
- Los ítems de la página llegan como
Object[]— haz el cast delitema tu tipo enbindItem. - No llames a APIs de UI dentro de
loadPageantes del callback — el adapter ya cambia a la thread de UI internamente al recibironPageLoaded. - Ajusta
maxCachedPagesal patrón de desplazamiento: un caché mayor evita recargas al volver, a costa de memoria.
Errores comunes
- Llamar a
onPageLoadedcon elpageIndexequivocado — el adapter usa ese índice para grabar en el caché e invalidar la franja correcta. - Bloquear en
loadPage— debe ser asíncrono; la thread de UI no puede esperar a la red.
Ver también
- Guía del área:
ui/· Recetas:cookbook/ - Componentes relacionados:
VirtualListView