Android अंतहीन सूची


232

मैं एक सूची कैसे बना सकता हूं, जहां जब आप सूची के अंत में पहुंच जाते हैं तो मुझे सूचित किया जाता है ताकि मैं और आइटम लोड कर सकूं?


9
मैं CommonWare के एंडलेस एडेप्टर की सलाह देता हूं: github.com/commonsguy/cwac-endless । मैंने इसे इस उत्तर से दूसरे प्रश्न के लिए पाया: stackoverflow.com/questions/4667064/…
टायलर कोलियर

मुझे एक ही चीज की जरूरत है..किसी एक की मदद? .. stackoverflow.com/questions/28122304/…

जवाबों:


269

एक उपाय यह है कि किसी विधि को लागू किया जाए OnScrollListenerऔर ListAdapterअपनी onScrollविधि में सुविधाजनक स्थिति में परिवर्तन (जैसे वस्तुओं को जोड़ना आदि) किया जाए ।

निम्नलिखित ListActivityपूर्णांक की एक सूची दिखाता है, 40 से शुरू होकर, आइटम को जोड़ना जब उपयोगकर्ता सूची के अंत तक स्क्रॉल करता है।

public class Test extends ListActivity implements OnScrollListener {

    Aleph0 adapter = new Aleph0();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(adapter); 
        getListView().setOnScrollListener(this);
    }

    public void onScroll(AbsListView view,
        int firstVisible, int visibleCount, int totalCount) {

        boolean loadMore = /* maybe add a padding */
            firstVisible + visibleCount >= totalCount;

        if(loadMore) {
            adapter.count += visibleCount; // or any other amount
            adapter.notifyDataSetChanged();
        }
    }

    public void onScrollStateChanged(AbsListView v, int s) { }    

    class Aleph0 extends BaseAdapter {
        int count = 40; /* starting amount */

        public int getCount() { return count; }
        public Object getItem(int pos) { return pos; }
        public long getItemId(int pos) { return pos; }

        public View getView(int pos, View v, ViewGroup p) {
                TextView view = new TextView(Test.this);
                view.setText("entry " + pos);
                return view;
        }
    }
}

आपको स्पष्ट रूप से लंबे समय तक चलने वाली क्रियाओं (जैसे वेब-डेटा लोड करना) के लिए अलग थ्रेड्स का उपयोग करना चाहिए और अंतिम सूची आइटम (जैसे बाजार या जीमेल एप्स करना) में प्रगति का संकेत देना चाह सकते हैं।


3
अगर आप स्क्रीन के बीच में स्क्रॉल करना बंद कर देंगे, तो क्या यह एडॉप्टर के आकार में वृद्धि को ट्रिगर नहीं करेगा? यह केवल अगले 10 को लोड करना चाहिए जब वास्तव में सूची तल पर पहुंच रहा हो।
मथियास

9
मैं BaseAdapter का उपयोग करके इस तरह के कई उदाहरण देखता हूं। उल्लेख करना चाहते हैं कि यदि आप डेटाबेस का उपयोग कर रहे हैं, तो एक SimpleCursorAdapter का उपयोग करने का प्रयास करें। जब आपको सूची में जोड़ना है, तो अपने डेटाबेस को अपडेट करें, एक नया कर्सर प्राप्त करें, और InformDataSetChanged के साथ SimpleCursorAdapter # changeCursor का उपयोग करें। कोई उपवर्ग की आवश्यकता नहीं है, और यह बेस एडेप्टर की तुलना में बेहतर प्रदर्शन करता है (फिर, केवल तभी जब आप डेटाबेस का उपयोग कर रहे हैं)।
ब्रैकेट

1
सूचनाडॉटसेटचेंज () को कॉल करने के बाद, यह सूची में सबसे ऊपर जाएगा, मैं इसे कैसे रोक सकता हूं?
ड्रा करें

2
एक नोट - मैंने इस दृष्टिकोण का उपयोग किया है, लेकिन दृश्यमान होने पर चेक जोड़ने की आवश्यकता है। 0. प्रत्येक सूची के लिए, मुझे ऑनक्राॅल में एक कॉलबैक मिलता है जहां फर्स्टविवेबल, विजुअलकाउंट और टोटलकाउंट सभी 0 हैं, जो तकनीकी रूप से सशर्त मिलते हैं, लेकिन नहीं जब मैं अधिक लोड करना चाहता हूं।
एरिक मिल

5
इस कोड के साथ एक और समस्या यह है कि firstVisible + visibleCount >= totalCountसुनने वाले को कई कॉल के साथ कई बार शर्त पूरी होती है। यदि लोड-अधिक फ़ंक्शन एक वेब अनुरोध है, (सबसे शायद यह होगा), तो एक और चेक जोड़ें कि क्या अनुरोध चल रहा है या नहीं। दूसरी ओर, जांचें कि क्या टोटकाउंट पिछले कुल गिनती के बराबर नहीं है, क्योंकि हमें सूची में समान संख्याओं के लिए कई अनुरोधों की आवश्यकता नहीं है।
सबिन सेबस्टियन

94

बस एक समाधान का योगदान करना चाहता था जिसका उपयोग मैंने अपने ऐप के लिए किया।

यह OnScrollListenerइंटरफ़ेस पर भी आधारित है, लेकिन मैंने पाया कि कम-एंड डिवाइस पर स्क्रॉलिंग का बेहतर प्रदर्शन है, क्योंकि स्क्रॉल ऑपरेशन के दौरान कोई भी दृश्य / कुल गणना गणना नहीं की जाती है।

  1. अपना ListFragmentया ListActivityअमल करने दोOnScrollListener
  2. उस वर्ग में निम्नलिखित विधियाँ जोड़ें:

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //leave this empty
    }
    
    @Override
    public void onScrollStateChanged(AbsListView listView, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) {
                currentPage++;
                //load more list items:
                loadElements(currentPage);
            }
        }
    }
    

    currentPageआपके डेटा स्रोत का पृष्ठ कहां है जिसे आपकी सूची में जोड़ा जाना चाहिए, और thresholdसूची आइटम (अंत से गिना गया) की संख्या है जो यदि दिखाई दे, तो लोडिंग प्रक्रिया को ट्रिगर करें। यदि आप उदाहरण के लिए सेट thresholdकरते हैं 0, तो उपयोगकर्ता को अधिक आइटम लोड करने के लिए सूची के बहुत अंत तक स्क्रॉल करना होगा।

  3. (वैकल्पिक) जैसा कि आप देख सकते हैं, "लोड-अधिक चेक" केवल तभी कहा जाता है जब उपयोगकर्ता स्क्रॉल करना बंद कर देता है। प्रयोज्य में सुधार करने के लिए, आप एक लोडिंग इंडिकेटर को सूची के अंत तक बढ़ा सकते हैं और जोड़ सकते हैं listView.addFooterView(yourFooterView)। ऐसे पाद दृश्य के लिए एक उदाहरण:

    <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/footer_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dp" >
    
        <ProgressBar
            android:id="@+id/progressBar1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical" />
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/progressBar1"
            android:padding="5dp"
            android:text="@string/loading_text" />
    
    </RelativeLayout>
    
  4. (वैकल्पिक) अंत में, listView.removeFooterView(yourFooterView)यदि कोई और आइटम या पृष्ठ नहीं हैं, तो कॉल करके उस लोडिंग इंडिकेटर को हटा दें ।


मैंने यह कोशिश की, लेकिन यह ListFragment के लिए काम नहीं करता है। इसे ListFragment में कैसे उपयोग किया जा सकता है।
जीशान

ठीक है, मैं इसे ListFragmentबिना किसी समस्या के साथ उपयोग करता हूं - बस ऊपर दिए गए प्रत्येक चरण का पालन करें और आप ठीक हो जाएंगे?) या आप कोई त्रुटि संदेश प्रदान कर सकते हैं?
साचोचर

आपको जो याद हो गया है उसे इस SO उत्तर में समझाया गया है: stackoverflow.com/a/6357957/1478093 -getListView().setOnScrollListener(this)
TBieniek

7
नोट: लिस्टव्यू पर पाद को जोड़ना और हटाना समस्याग्रस्त है (पाद प्रदर्शित नहीं होता है अगर setAdapter को पाद लेख जोड़ने से पहले कहा जाता है), मैंने इसे हटाए बिना सीधे पाद दृश्य के दृश्यता को संशोधित किया।
डीवीडी

लोड-बस्तियों (करेंटपेज) में क्या जोड़ा जाना है ??? मेरा मतलब है कि मैं अपने AsyncTask या एक धागा कहते हैं?
android_developer

20

आप सूची के अंत का पता लगा सकते हैं onScrollListener की मदद से , वर्किंग कोड नीचे प्रस्तुत किया गया है:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
        Log.v(TAG, "onListEnd, extending list");
        mPrevTotalItemCount = totalItemCount;
        mAdapter.addMoreData();
    }
}

ऐसा करने का एक और तरीका है (एडाप्टर के अंदर) निम्नानुसार है:

    public View getView(int pos, View v, ViewGroup p) {
            if(pos==getCount()-1){
                addMoreData(); //should be asynctask or thread
            }
            return view;
    }

विदित हो कि इस विधि को कई बार कहा जाएगा, इसलिए आपको कई कॉल को ब्लॉक करने के लिए एक और शर्त जोड़ना होगी addMoreData()

जब आप सूची में सभी तत्वों को जोड़ते हैं, तो कृपया व्यू को अपडेट करने के लिए अपने एडेप्टर के अंदर InformDataSetChanged () कॉल करें (यह UI थ्रेड पर चलाया जाना चाहिए - runOnUiThread )


7
किसी दृश्य को वापस करने के बजाय अन्य सामान करना बुरा है getView। उदाहरण के लिए, आप posउपयोगकर्ता द्वारा देखे जाने की गारंटी नहीं देते हैं । यह बस ListView मापने के सामान हो सकता है।
थॉमस अहले

मैं 10 आइटम स्क्रॉल किए जाने के बाद और आइटम लोड करना चाहता हूं। लेकिन मुझे लगता है कि 10 वीं आइटम से पहले लोडिंग शुरू होती है, 9 वें आइटम पर दिखाई दे रहा है। तो इसे कैसे रोकें?
अतुल भारद्वाज

4

पर Ognyan Bankov GitHubमैं एक सरल और काम कर समाधान मिल गया!

यह इसका उपयोग करता है Volley HTTP libraryजो Android ऐप्स के लिए नेटवर्किंग को आसान और सबसे महत्वपूर्ण, तेज़ बनाता है। वॉली खुले एओएसपी रिपॉजिटरी के माध्यम से उपलब्ध है।

दिया गया कोड प्रदर्शित करता है:

  1. सूची दृश्य जो HTTP पृष्ठबद्ध अनुरोधों से आबाद है।
  2. NetworkImageView का उपयोग।
  3. "अंतहीन" सूची-दृश्य पृष्ठ-विभाजन पढ़ने-आगे के साथ।

भविष्य की निरंतरता के लिए मैंने बैंकोव के रेपो को त्याग दिया


2

यहां एक समाधान है जो लोड करते समय ListView के अंत में एक लोडिंग दृश्य दिखाना आसान बनाता है।

आप यहां कक्षाएं देख सकते हैं:

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - हेल्पर इसे संभव बनाने के लिए उपयोग करें। SimpleListViewWithLoadingIndicator से विस्तार किए बिना सुविधाएँ।

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - श्रोता जो उपयोगकर्ता को डेटा लोड करते समय शुरू करता है। ListView के निचले भाग तक पहुंचने वाला है।

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - EndlessListView। आप इस क्लास को सीधे इस्तेमाल कर सकते हैं या इससे बढ़ा सकते हैं।


1

थोड़ी देर हो सकती है लेकिन निम्नलिखित समाधान मेरे मामले में बहुत उपयोगी है। एक तरह से आपको बस इतना करना है कि अपनी सूची में जोड़ें Footerऔर इसके लिए बनाएं addOnLayoutChangeListener

http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)

उदाहरण के लिए:

ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView
View loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more, null); // Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
listView1.addFooterView(loadMoreView); // Adding your View to your listview 

...

loadMoreView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
         Log.d("Hey!", "Your list has reached bottom");
    }
});

यह घटना एक बार फायर करती है जब एक पाद दिखाई देता है और एक आकर्षण की तरह काम करता है।


0

इस समस्या की कुंजी लोड-अधिक ईवेंट का पता लगाना, डेटा के लिए एक async अनुरोध शुरू करना और फिर सूची को अपडेट करना है। इसके अलावा लोडिंग इंडिकेटर और अन्य डेकोरेटर्स के साथ एडॉप्टर की जरूरत होती है। वास्तव में, समस्या कुछ कोने के मामलों में बहुत जटिल है। बस एक OnScrollListenerकार्यान्वयन पर्याप्त नहीं है, क्योंकि कभी-कभी आइटम स्क्रीन को नहीं भरते हैं।

मैंने एक व्यक्तिगत पैकेज लिखा है, जो अंतहीन सूची का समर्थन करता है RecyclerView, और एक async लोडर कार्यान्वयन भी प्रदान करता है AutoPagerFragmentजो बहु-पृष्ठ स्रोत से डेटा प्राप्त करना बहुत आसान बनाता है। यह किसी भी पृष्ठ RecyclerViewको किसी कस्टम ईवेंट में लोड कर सकता है , न कि अगले पृष्ठ पर।

यहाँ पता है: https://github.com/SphiaTower/AutoPagerRecyclerManager


लिंक टूट गया है।
DSlomer64

0

अब तक का सबसे अच्छा समाधान जो मैंने देखा है, वह पुनर्नवीनीकरण विचारों के लिए फास्टएडस्केप पुस्तकालय में है। यह एक है EndlessRecyclerOnScrollListener

यहाँ एक उदाहरण का उपयोग किया गया है: EndlessScrollListActivity

एक बार जब मैंने इसे अंतहीन स्क्रॉलिंग सूची के लिए उपयोग किया तो मुझे महसूस हुआ कि सेटअप बहुत मजबूत है। मैं निश्चित रूप से इसकी सिफारिश करूंगा।


0

मैं उसी के समान एक अन्य समाधान में काम कर रहा हूं, लेकिन, मैं footerViewउपयोगकर्ता को डाउनलोड करने के लिए अधिक तत्वों को डाउनलोड करने की संभावना देने के लिए footerViewएक का उपयोग कर रहा हूं, मैं एक "मेनू" का उपयोग कर रहा हूं जो ऊपर ListViewऔर नीचे दिखाया गया है। माता-पिता का दृश्य, यह "मेनू" नीचे छिपाता है ListView, इसलिए, जब listViewमेनू स्क्रॉल हो रहा हो तो गायब हो जाता है और जब स्क्रॉल स्थिति निष्क्रिय होती है, तो मेनू फिर से दिखाई देता है, लेकिन जब उपयोगकर्ता के अंत तक स्क्रॉल करता है listView, तो मैं "पूछता हूं" पता है कि क्या footerViewउस मामले में दिखाया गया है, मेनू दिखाई नहीं देता है और उपयोगकर्ता footerViewअधिक सामग्री लोड करने के लिए देख सकता है। यहाँ कोड है:

सादर।

listView.setOnScrollListener(new OnScrollListener() {

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // TODO Auto-generated method stub
        if(scrollState == SCROLL_STATE_IDLE) {
            if(footerView.isShown()) {
                bottomView.setVisibility(LinearLayout.INVISIBLE);
            } else {
                bottomView.setVisibility(LinearLayout.VISIBLE);
            } else {
                bottomView.setVisibility(LinearLayout.INVISIBLE);
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {

    }
});

0

मुझे पता है कि इसका एक पुराना सवाल है और एंड्रॉइड की दुनिया ज्यादातर रिसाइकलर व्यू में चली गई है, लेकिन किसी भी इच्छुक व्यक्ति के लिए, आपको यह लाइब्रेरी बहुत दिलचस्प लग सकती है ।

यह सूची देखने के लिए उपयोग किए गए बेस एडेप्टर का उपयोग यह पता लगाने के लिए करता है कि सूची को अंतिम आइटम पर स्क्रॉल किया गया है या जब इसे अंतिम आइटम से दूर स्क्रॉल किया जा रहा है।

यह एक उदाहरण परियोजना (गतिविधि कोड की बमुश्किल 100 लाइनें) के साथ आता है जिसका उपयोग यह समझने के लिए किया जा सकता है कि यह कैसे काम करता है।

सरल उपयोग:

class Boy{

private String name;
private double height;
private int age;
//Other code

}

लड़का वस्तुओं को रखने के लिए एक एडॉप्टर लगेगा:


public class BoysAdapter extends EndlessAdapter<Boy>{




        ViewHolder holder = null;


        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(parent
                    .getContext());

            holder = new ViewHolder();

            convertView = inflater.inflate(
                    R.layout.list_cell, parent, false);


            holder.nameView = convertView.findViewById(R.id.cell);

            // minimize the default image.
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Boy boy = getItem(position);

        try {
            holder.nameView.setText(boy.getName());

            ///Other data rendering codes.

        } catch (Exception e) {
            e.printStackTrace();
        }

        return super.getView(position,convertView,parent);

}

ध्यान दें कि कैसे बॉयज एडाप्टर का गेटव्यू तरीका एंडलेस एडेप्टर सुपरक्लास की विधि को कॉल करता है getView। यह 100% आवश्यक है।

अब एडेप्टर बनाने के लिए, करें:

   adapter = new ModelAdapter() {
            @Override
            public void onScrollToBottom(int bottomIndex, boolean moreItemsCouldBeAvailable) {

                if (moreItemsCouldBeAvailable) { 
                    makeYourServerCallForMoreItems();
                } else {
                    if (loadMore.getVisibility() != View.VISIBLE) {
                        loadMore.setVisibility(View.VISIBLE);
                    }
                }
            }

            @Override
            public void onScrollAwayFromBottom(int currentIndex) { 
                loadMore.setVisibility(View.GONE);
            }

            @Override
            public void onFinishedLoading(boolean moreItemsReceived) { 
                if (!moreItemsReceived) {
                    loadMore.setVisibility(View.VISIBLE);
                }
            }
        };

loadMoreआइटम एक बटन या अन्य ui तत्व यह है कि यूआरएल से अधिक डेटा लाने के लिए क्लिक किया जा सकता है। जब कोड में वर्णित के रूप में रखा जाता है, तो एडेप्टर को पता है कि उस बटन को कब दिखाना है और कब अक्षम करना है। बस अपने xml में बटन बनाएं और इसे ऊपर दिए गए एडॉप्टर कोड में दिखाए।

का आनंद लें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.