This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
PagedDataAdapter
PagedDataAdapter is a paged DataAdapter for VirtualListView, with an LRU page cache. It keeps only a few pages in memory; when scrolling to a region whose page was discarded, it shows a spinner and reloads asynchronously via loadPage.
It is an abstract class: you implement getTotalCount, loadPage, createView and bindItem. The index→page translation, the cache, the spinner and the scroll lock during loading come ready-made.
🔴 · Package:
dev.crossfly.ui· Implements:VirtualListView.DataAdapter· Usage: passed to theVirtualListViewconstructor
When to use
- Data that comes from network/database in pages and does not all fit in memory.
- You want automatic caching (LRU) with transparent reloading when returning to an old region.
When NOT to use
- All data is already in memory → implement
DataAdapterdirectly on theVirtualListView. - Small list →
ListView.
Complete example (copy, paste and run)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Relative
/** Runnable main screen. Point the launcher (classname) and run: 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 items/page, 5 pages
public int getTotalCount() { return total; }
public void loadPage(int pageIndex, PageCallback cb) {
// Simulates a load (replace with a network/DB call in the 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); // lists use LAY_FILL (they absorb the height)
}
}
The snippets below show only the core (what goes inside
onShow()). To run them, place them in theMainWindowskeleton above.
Basic usage
PagedDataAdapter adapter = new PagedDataAdapter(20, 5) { // 20 items/page, 5 pages in memory
public int getTotalCount() { return serverTotal; }
public void loadPage(int pageIndex, PageCallback cb) {
api.fetch(pageIndex, data -> cb.onPageLoaded(pageIndex, data)); // can be 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);
Constructors
| Constructor | Description |
|---|---|
PagedDataAdapter(int pageSize, int maxCachedPages) |
pageSize: items per page. maxCachedPages: pages kept in memory (LRU) |
Both fields are public final. The VirtualListView injects itself into the adapter when you pass this adapter to its constructor.
Abstract methods to implement
| Method | Description |
|---|---|
int getTotalCount() |
Total items on the server (used by getCount()) |
void loadPage(int pageIndex, PageCallback callback) |
Loads a page asynchronously; call callback.onPageLoaded(pageIndex, items) when done (from any thread) |
Component createView() throws Exception |
Creates a blank view |
void bindItem(Component view, Object item, int index) throws Exception |
Binds the raw item (Object) to the view — cast it to your type |
Useful properties and methods
| Method | Type | What it does |
|---|---|---|
isAvailable(int index) |
boolean |
Whether the item is already in the cache |
clearCache() |
void |
Clears cache and loading state |
getCount() |
int |
Delegates to getTotalCount() |
How it works (summary)
bindView(view, index)translatespageIndex = index / pageSizeanditemInPage = index % pageSize.- Page in cache → immediate
bindItem(waitingForData = false). - Page missing →
waitingForData = trueand it firesrequestPage(pageIndex).
- Page in cache → immediate
requestPageavoids duplicate requests (loading), shows the spinner and pauses the fling; when the callback returns, it marshals to the UI thread withComponent.onUI(...), records the page, hides the spinner, forces a re-bind of the range (invalidateRange) and resumes the fling.- The
cacheis aLinkedHashMapin access-order mode that discards the oldest page (LRU) when it exceedsmaxCachedPages.
Callbacks and events
| Callback | When it fires |
|---|---|
PageCallback.onPageLoaded(int pageIndex, Object[] items) |
You call it when done loading the page (from any thread) |
States
waitingForData—truewhile a page is loading; signals to theVirtualListViewto lock the scroll.- LRU — old pages are discarded; when scrolling back, they are reloaded (new spinner + request).
Example — cast of a typed item
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 of the raw Object
((Label) view).setText(c.getNome());
}
};
VirtualListView list = new VirtualListView(Relative.ofFont(2.4f), adapter);
Best practices
- The page items arrive as
Object[]— cast theitemto your type inbindItem. - Do not call UI APIs inside
loadPagebefore the callback — the adapter already switches to the UI thread internally upon receivingonPageLoaded. - Adjust
maxCachedPagesto the scrolling pattern: a larger cache avoids reloads when returning, at the cost of memory.
Common mistakes
- Calling
onPageLoadedwith the wrongpageIndex— the adapter uses that index to record in the cache and invalidate the correct range. - Blocking in
loadPage— it must be asynchronous; the UI thread cannot wait for the network.
See also
- Area guide:
ui/· Recipes:cookbook/ - Related components:
VirtualListView