本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
如何显示包含数千项的虚拟列表
目的。 显示数万个项目而无需为每一行创建一个 Component。
VirtualListView 只创建/渲染可见的视图,并回收移出屏幕的视图(就像 Android 的
RecyclerView)。所有行都具有固定高度(Relative itemHeight)。
使用的 API
new VirtualListView(Relative itemHeight, DataAdapter adapter)— 唯一构造函数;所有行的高度都是固定的。interface DataAdapter(嵌套在VirtualListView中),包含三个方法:int getCount()— 项目总数。Component createView() throws Exception— 创建一个空白视图;仅在回收池为空时调用。void bindView(Component view, int index) throws Exception— 用索引处的数据填充视图(新建或回收的)。
VirtualListView.notifyDataChanged()— 在数据集在新索引下增长/变化后调用(例如:追加了一页)。不会重新绑定已可见的行。VirtualListView.reloadData()— 完全重载:丢弃视图缓存、回收所有内容、滚动到顶部并重新绑定所有可见的槽位。用于搜索/过滤/排序(内容在相同索引下发生变化)。VirtualListView.scrollToIndex(int index)— 滚动至使索引居中。VirtualListView.getScrollY()— 当前垂直偏移量(以像素为单位,对可折叠头部很有用)。
完整示例(复制、粘贴并运行)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Relative(用于 VirtualListView)
/** 可执行的主界面。将 launcher 指向此类(classname)并运行:gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
final String[] dados = new String[50_000];
for (int i = 0; i < dados.length; i++) dados[i] = "Registro " + i;
Relative alturaItem = Relative.ofFont(3f); // 每行约 3 倍字体高度(随 UI 缩放)
VirtualListView lista = new VirtualListView(alturaItem, new VirtualListView.DataAdapter()
{
public int getCount()
{
return dados.length;
}
public Component createView() throws Exception
{
// 可复用的 "空" view — 这里没有数据
return new Label("");
}
public void bindView(Component view, int index) throws Exception
{
// 用当前索引的数据填充回收的 view
((Label) view).setText(dados[index]);
}
});
add(LAY_FILL, lista);
}
}
下面的片段只展示核心部分。要运行它,请将其放入上面的
MainWindow骨架中。
最小片段
// 已在源码核实:VirtualListView.java(DataAdapter 是嵌套接口)
final String[] dados = new String[50_000];
for (int i = 0; i < dados.length; i++) dados[i] = "Registro " + i;
Relative alturaItem = Relative.ofFont(3f); // 每行约 3 倍字体高度(随 UI 缩放)
VirtualListView lista = new VirtualListView(alturaItem, new VirtualListView.DataAdapter()
{
public int getCount()
{
return dados.length;
}
public Component createView() throws Exception
{
// 可复用的 "空" view — 这里没有数据
return new Label("");
}
public void bindView(Component view, int index) throws Exception
{
// 用当前索引的数据填充回收的 view
((Label) view).setText(dados[index]);
}
});
layout.add(1f, lista);
更新数据:
// 我向末尾追加了更多项(新索引)→ notifyDataChanged
carregarMaisDados(dados);
lista.notifyDataChanged();
// 我应用了筛选/搜索(相同索引,内容不同)→ reloadData
aplicarFiltro();
lista.reloadData(); // 回收,回到顶部并重新绑定可见项
深入了解
- 关键规则:绝不要在多次绑定之间保存对视图的引用——它们会被回收用于其他索引。
- 一行包含多个元素(图标 + 文本 + 数值)?创建一个自定义
Component,带一个bind(...)方法,将子引用作为字段保存:createView()返回new CardTarefa(),而bindView执行((CardTarefa) view).bind(dados[index])(参见 以组件方式思考)。 - 数据按页从服务器获取:参见 paginacao.md(使用
PagedDataAdapter)。 - 通过追加实现无限滚动:参见 carregar-mais.md。
- 组件指南:VirtualListView · 最佳实践:性能与大型列表 · 权威来源:第 15 章
这个页面有帮助吗?感谢你的反馈!