यह पृष्ठ पुर्तगाली से मशीन-अनुवादित है और इसमें त्रुटियाँ हो सकती हैं। पुर्तगाली संस्करण प्रामाणिक है।
VirtualListView
VirtualListView एक वर्चुअलाइज़्ड सूची है: यह केवल स्क्रीन पर दिखाई देने वाले आइटम बनाती और रेंडर करती है और viewport से बाहर जाने वाले घटकों को रीसायकल करती है, Android के RecyclerView की शैली में। यह कुछ दर्जन जीवित घटकों के साथ हज़ारों (या लाखों) आइटम का समर्थन करती है, मेमोरी उपयोग को स्थिर रखते हुए।
डेटा स्रोत DataAdapter इंटरफ़ेस है (getCount / createView / bindView)। प्रत्येक आइटम की ऊँचाई निश्चित होती है (Relative itemHeight)। इसमें “और लोड करें” कॉलबैक (onLoadMore) और लोडिंग स्पिनर शामिल हैं।
🔴 · पैकेज:
dev.crossfly.ui· विस्तार करता है:Component· स्टाइल:VirtualListViewStyle(getSkin().virtualListView()के माध्यम से)
कब उपयोग करें
- बड़ी सूचियाँ (सैकड़ों हज़ार पंक्तियाँ) जहाँ प्रति आइटम एक घटक बनाना अव्यवहारिक है।
- वृद्धिशील लोडिंग के साथ अनंत स्क्रॉलिंग (
onLoadMore)। - कैश के साथ रिमोट पेजिनेशन →
PagedDataAdapterके साथ जोड़ें।
कब उपयोग न करें
- टेक्स्ट की छोटी सूचियाँ →
ListViewअधिक सरल है और सटीक ऊँचाई मापता है। - वास्तव में परिवर्तनशील आइटम ऊँचाइयाँ — यहाँ ऊँचाई निश्चित है (एक ऐसा स्लॉट चुनें जो सबसे बड़े आइटम को समा सके)।
दिखावट
समान ऊँचाई वाले आइटम का ऊर्ध्वाधर स्क्रॉल करने योग्य कॉलम। स्क्रॉल के दौरान, स्क्रीन से बाहर के आइटम एक पूल में एकत्र किए जाते हैं और पुनः उपयोग किए जाते हैं। एक वैकल्पिक स्पिनर फ़ुटर में (load-more) या केंद्र में (पेज लोडिंग) दिखाई देता है।
पूर्ण उदाहरण (कॉपी करें, पेस्ट करें और चलाएँ)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.graphics.*; // Relative
import java.util.*; // List, ArrayList
/** चलाने योग्य मुख्य स्क्रीन। launcher (classname) की ओर संकेत करें और चलाएँ: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
final List<String> items = new ArrayList<>();
for (int i = 0; i < 10_000; i++)
items.add("Item " + i);
VirtualListView list = new VirtualListView(Relative.ofFont(2f),
new VirtualListView.DataAdapter() {
public int getCount() { return items.size(); }
public Component createView() { return new Label(""); }
public void bindView(Component v, int index) {
((Label) v).setText(items.get(index));
}
});
add(LAY_FILL, list); // सूचियां LAY_FILL उपयोग करती हैं (ऊंचाई अवशोषित करती हैं)
}
}
नीचे दिए गए अंश केवल मुख्य भाग दिखाते हैं (जो
onShow()के अंदर जाता है)। चलाने के लिए, उन्हें ऊपर दिए गएMainWindowढाँचे में रखें।
बुनियादी उपयोग
VirtualListView list = new VirtualListView(Relative.ofFont(2f),
new VirtualListView.DataAdapter() {
public int getCount() { return items.size; }
public Component createView() { return new Label(""); }
public void bindView(Component v, int index) {
((Label) v).setText("Item " + index);
}
});
layout.add(LAY_FILL, list);
कंस्ट्रक्टर
| कंस्ट्रक्टर | विवरण |
|---|---|
VirtualListView(Relative itemHeight, DataAdapter adapter) |
एकमात्र कंस्ट्रक्टर। itemHeight प्रत्येक आइटम की निश्चित ऊँचाई है; adapter डेटा स्रोत है |
कोई तर्क-रहित कंस्ट्रक्टर नहीं है। यदि
adapternullहै, तो कंस्ट्रक्टरcreateAdapter()कॉल करता है (जिसे आप एक सबक्लास में ओवरराइड करते हैं)। यदि adapter एकPagedDataAdapterहै, तो कंस्ट्रक्टर स्वचालित रूप से उसमेंthisइंजेक्ट करता है।
DataAdapter
public interface DataAdapter {
int getCount(); // आइटम की कुल संख्या
Component createView() throws Exception; // खाली व्यू बनाता है (सिर्फ़ तभी जब pool खाली हो)
void bindView(Component view, int index) throws Exception; // इंडेक्स का डेटा व्यू से जोड़ता है
}
getCount()कुल की जानकारी देता है — सूची सभी आइटम को मटेरियलाइज़ किए बिनाcount * itemHeightकी ऊँचाई का दिखावा करती है।createView()केवल तब कॉल होता है जब रीसाइक्लिंग पूल खाली होता है।bindView()स्क्रॉल के दौरान कई बार चलता है: इसे आइडेम्पोटेंट और सस्ता रखें।
गुण और अनुकूलन
| गुण / मेथड | प्रकार | डिफ़ॉल्ट | क्या करता है |
|---|---|---|---|
onLoadMore(Runnable) |
VirtualListView |
null |
अंत के पास स्क्रॉल करने पर सक्रिय होने वाला कॉलबैक |
loadMoreThreshold(int) |
VirtualListView |
5 |
अंत से कितने आइटम पहले load-more सक्रिय करते हैं (vlvStyle() में लिखता है) |
notifyDataChanged() |
void |
— | डेटा जोड़ने के बाद कॉल करें (नया पेज); स्क्रॉल को री-क्लैंप करता है और सीमा को री-बाइंड करता है |
reloadData() |
void |
— | समान इंडेक्स के तहत सामग्री बदलने के बाद कॉल करें (खोज/फ़िल्टर/सॉर्ट); कैश साफ़ करता है, शीर्ष पर स्क्रॉल करता है, सब कुछ री-बाइंड करता है |
scrollToIndex(int) |
void |
— | आइटम को viewport में केंद्रित करता है |
scrollToY(float) |
void |
— | पिक्सेल में एक ऑफ़सेट तक स्क्रॉल करता है (सब-पिक्सेल/एनिमेट करने योग्य) |
getScrollY() |
float |
— | वर्तमान ऊर्ध्वाधर ऑफ़सेट (कोलैप्स करने योग्य हेडर के लिए उपयोगी) |
setItemHeight(Relative) |
void |
— | आइटम की ऊँचाई बदलता है और notifyDataChanged() कॉल करता है |
getItemHeight() |
int |
— | px में आइटम की ऊँचाई |
replaceView(int, Component) |
void |
— | किसी इंडेक्स की सक्रिय view को पूरी तरह से नए घटक से बदलता है |
कॉलबैक और इवेंट
| कॉलबैक | कब सक्रिय होता है |
|---|---|
onLoadMore(Runnable) |
जब lastVisible >= count - threshold और कोई लोडिंग लंबित नहीं है |
स्क्रॉल इवेंट (onPan/onFling/onMouseWheel) तब तक अवरुद्ध रहते हैं जब तक पेजिनेटेड adapter डेटा की प्रतीक्षा करता है (isWaitingForData()), जिससे खालीपन में स्क्रॉल करने से बचा जाता है।
स्थितियाँ
- रीसाइक्लिंग — viewport से बाहर के आइटम पूल में वापस जाते हैं; पुनः प्रवेश करने पर, वे
bindViewके माध्यम से री-बाइंड होते हैं। - लोडिंग (load-more) — फ़ुटर में स्पिनर,
notifyDataChanged()तकloadMorePending = true। - पेज की प्रतीक्षा (
PagedDataAdapterके साथ) — पेज आने तक स्क्रॉल लॉक रहता है।
load-more के साथ 10,000 आइटम की सूची
VirtualListView list = new VirtualListView(Relative.ofFont(2f),
new VirtualListView.DataAdapter() {
public int getCount() { return items.size; }
public Component createView() { return new Label(""); }
public void bindView(Component v, int index) {
((Label) v).setText("Item " + index);
}
});
list.onLoadMore(() -> {
carregarProximaPagina(); // स्रोत में आइटम जोड़ता है
list.notifyDataChanged(); // सूची को सूचित करता है
});
layout.add(LAY_FILL, list);
सबक्लास के माध्यम से adapter का गतिशील परिवर्तन
बेस क्लास में कोई सार्वजनिक setAdapter नहीं है (adapter फ़ील्ड protected है)। रनटाइम पर adapter बदलने के लिए, एक सबक्लास बनाएँ:
class RowList extends VirtualListView {
RowList() { super(Relative.ofFont(2f), null); }
void setAdapter(DataAdapter a, Relative h) { adapter = a; setItemHeight(h); }
}
RowList vsc = new RowList();
final int count = 2000;
vsc.setAdapter(new VirtualListView.DataAdapter() {
public int getCount() { return count; }
public Component createView() { return new Label(""); }
public void bindView(Component v, int index) {
((Label) v).setText("Row id: " + index);
}
}, Relative.ofPixels(100));
अच्छी प्रथाएँ
- आइटम की ऊँचाई निश्चित है — एक ऐसा स्लॉट चुनें जो सबसे बड़े आइटम को समा सके।
- डेटा जोड़ने के बाद,
notifyDataChanged()कॉल करें; समान इंडेक्स के तहत सामग्री बदलने के बाद,reloadData()कॉल करें (अन्यथा पहले से दिखाई देने वाली पंक्तियाँ पुराने डेटा के साथ रह जाती हैं)। - यदि
bindViewरीसायकल की गई view को म्यूटेट करने के बजाय प्रति इंडेक्स एक नया घटक बनाता है, तोreplaceView(...)का उपयोग करें — या स्वीकार करें कि वे views पूल में वापस नहीं जातीं।
आम गलतियाँ
bindViewमें भारी संसाधन आवंटित करना — यह प्रत्येक स्क्रॉल इवेंट पर चलता है। बाइंडिंग को सस्ता रखें।- पेज जोड़ने के बाद
notifyDataChanged()भूल जाना — नई सामग्री ऊँचाई को पहचाना नहीं जाता और load-more रीसेट नहीं होता। - केवल जोड़ा तो
reloadData()का उपयोग करना — यह शीर्ष पर स्क्रॉल करता है; append के लिएnotifyDataChanged()का उपयोग करें।
यह भी देखें
- क्षेत्र गाइड:
ui/· रेसिपी:cookbook/ - संबंधित घटक:
PagedDataAdapter·ListView