मुख्य सामग्री पर जाएँ
CrossFly 100% ओपन सोर्सGitHub पर फ़ॉलो करें
CrossFlyCrossFly
शुरू करें

यह पृष्ठ पुर्तगाली से मशीन-अनुवादित है और इसमें त्रुटियाँ हो सकती हैं। पुर्तगाली संस्करण प्रामाणिक है।

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 डेटा स्रोत है

कोई तर्क-रहित कंस्ट्रक्टर नहीं है। यदि adapter null है, तो कंस्ट्रक्टर 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() का उपयोग करें।

यह भी देखें

क्या यह पृष्ठ उपयोगी था?