RecyclerView के साथ डाइनैमिक सूचियां बनाना Android Jetpack का हिस्सा.
RecyclerView की मदद से, डेटा के बड़े सेट को आसानी से और असरदार तरीके से दिखाया जा सकता है. आपको डेटा देना होता है और यह तय करना होता है कि हर आइटम कैसा दिखेगा. इसके बाद, RecyclerView लाइब्रेरी ज़रूरत के हिसाब से एलिमेंट बनाती है.
नाम से ही पता चलता है कि RecyclerView, उन अलग-अलग एलिमेंट को रीसाइकल करता है. जब कोई आइटम स्क्रोल करके स्क्रीन से हटा दिया जाता है, तो RecyclerView उसका व्यू नहीं मिटाता. इसके बजाय, RecyclerView स्क्रीन पर स्क्रोल किए गए नए आइटम के लिए व्यू का फिर से इस्तेमाल करता है. RecyclerView से परफ़ॉर्मेंस और ऐप्लिकेशन की रिस्पॉन्सिवनेस बेहतर होती है. साथ ही, इससे बैटरी की खपत कम होती है.
मुख्य क्लास
आपकी डाइनैमिक सूची बनाने के लिए, कई क्लास एक साथ काम करती हैं.
RecyclerView
,ViewGroup
होता है. इसमें आपके डेटा से जुड़े व्यू शामिल होते हैं. यह एक व्यू है. इसलिए, इसे अपने लेआउट में उसी तरह जोड़ा जाता है जिस तरह कोई अन्य यूज़र इंटरफ़ेस (यूआई) एलिमेंट जोड़ा जाता है. इसके लिए,RecyclerView
का इस्तेमाल किया जाता है.सूची में मौजूद हर एलिमेंट को व्यू होल्डर ऑब्जेक्ट से तय किया जाता है. व्यू होल्डर बनाए जाने पर, उससे कोई डेटा जुड़ा नहीं होता. व्यू होल्डर बनाने के बाद,
RecyclerView
इसे अपने डेटा से बाइंड करता है.RecyclerView.ViewHolder
को बढ़ाकर व्यू होल्डर को तय किया जाता है.RecyclerView
, व्यू का अनुरोध करता है और ऐडॉप्टर में मौजूद तरीकों को कॉल करके, व्यू को उनके डेटा से बाइंड करता है.RecyclerView.Adapter
को बढ़ाकर अडैप्टर तय किया जाता है.लेआउट मैनेजर, आपकी सूची में मौजूद हर एलिमेंट को व्यवस्थित करता है. RecyclerView लाइब्रेरी की ओर से उपलब्ध कराए गए लेआउट मैनेजर में से किसी एक का इस्तेमाल किया जा सकता है. इसके अलावा, आपके पास अपना लेआउट मैनेजर तय करने का विकल्प भी होता है. सभी लेआउट मैनेजर, लाइब्रेरी की
LayoutManager
ऐब्स्ट्रैक्ट क्लास पर आधारित होते हैं.
RecyclerView के सैंपल ऐप्लिकेशन (Kotlin) या RecyclerView के सैंपल ऐप्लिकेशन (Java) में जाकर, यह देखा जा सकता है कि सभी कॉम्पोनेंट एक साथ कैसे काम करते हैं.
RecyclerView को लागू करने का तरीका
अगर आपको RecyclerView का इस्तेमाल करना है, तो आपको कुछ काम करने होंगे. इनके बारे में यहां बताया गया है.
तय करें कि सूची या ग्रिड कैसा दिखेगा. आम तौर पर, RecyclerView लाइब्रेरी के स्टैंडर्ड लेआउट मैनेजर में से किसी एक का इस्तेमाल किया जा सकता है.
तय करें कि सूची में मौजूद हर एलिमेंट कैसा दिखेगा और कैसे काम करेगा. इस डिज़ाइन के आधार पर,
ViewHolder
क्लास को बढ़ाएं. आपके वर्शन में,ViewHolder
आपकी सूची के आइटम के लिए सभी सुविधाएं उपलब्ध हैं. आपका व्यू होल्डर,View
के चारों ओर एक रैपर होता है. साथ ही, उस व्यू कोRecyclerView
मैनेज करता है.Adapter
तय करें, जो आपके डेटा कोViewHolder
व्यू से जोड़ता है.
एडवांस लेवल पर पसंद के मुताबिक बनाने के विकल्प भी उपलब्ध हैं. इनकी मदद से, RecyclerView को अपनी ज़रूरतों के हिसाब से बनाया जा सकता है.
लेआउट प्लान करना
आपके RecyclerView में मौजूद आइटम, LayoutManager
क्लास के हिसाब से व्यवस्थित किए जाते हैं. RecyclerView लाइब्रेरी, तीन लेआउट मैनेजर उपलब्ध कराती है. ये लेआउट मैनेजर, लेआउट से जुड़ी सबसे आम समस्याओं को हल करते हैं:
LinearLayoutManager
आइटम को एक डाइमेंशन वाली सूची में व्यवस्थित करता है.GridLayoutManager
आइटम को दो डाइमेंशन वाली ग्रिड में व्यवस्थित करता है:- अगर ग्रिड को वर्टिकल तौर पर व्यवस्थित किया गया है, तो
GridLayoutManager
हर लाइन में मौजूद सभी एलिमेंट की चौड़ाई और ऊंचाई को एक जैसा बनाने की कोशिश करता है. हालांकि, अलग-अलग लाइनों की ऊंचाई अलग-अलग हो सकती है. - अगर ग्रिड को हॉरिज़ॉन्टल तौर पर व्यवस्थित किया गया है, तो
GridLayoutManager
हर कॉलम के सभी एलिमेंट की चौड़ाई और ऊंचाई एक जैसी रखने की कोशिश करता है. हालांकि, अलग-अलग कॉलम की चौड़ाई अलग-अलग हो सकती है.
- अगर ग्रिड को वर्टिकल तौर पर व्यवस्थित किया गया है, तो
StaggeredGridLayoutManager
,GridLayoutManager
के जैसा ही होता है. हालांकि, इसमें यह ज़रूरी नहीं है कि किसी लाइन में मौजूद आइटम की ऊंचाई (वर्टिकल ग्रिड के लिए) एक जैसी हो या एक ही कॉलम में मौजूद आइटम की चौड़ाई (हॉरिज़ॉन्टल ग्रिड के लिए) एक जैसी हो. इस वजह से, लाइन या कॉलम में मौजूद आइटम एक-दूसरे से अलग हो सकते हैं.
आपको हर आइटम का लेआउट भी डिज़ाइन करना होगा. आपको इस लेआउट की ज़रूरत तब पड़ती है, जब व्यू होल्डर को डिज़ाइन किया जाता है. इसके बारे में अगले सेक्शन में बताया गया है.
अडैप्टर और व्यू होल्डर लागू करना
लेआउट तय करने के बाद, आपको Adapter
और ViewHolder
लागू करना होगा. ये दोनों क्लास एक साथ काम करती हैं. इनसे यह तय होता है कि आपका डेटा कैसे दिखाया जाएगा. ViewHolder
, View
के चारों ओर मौजूद एक रैपर है. इसमें सूची के किसी आइटम का लेआउट होता है. Adapter
, ज़रूरत के हिसाब से ViewHolder
ऑब्जेक्ट बनाता है. साथ ही, उन व्यू के लिए डेटा भी सेट करता है. व्यू को उनके डेटा से जोड़ने की प्रोसेस को बाइंडिंग कहा जाता है.
अडैप्टर तय करते समय, तीन मुख्य तरीकों को बदला जाता है:
onCreateViewHolder()
:RecyclerView
इस तरीके को तब कॉल करता है, जब उसे नयाViewHolder
बनाना होता है. यह तरीका,ViewHolder
और उससे जुड़ेView
को बनाता है और उन्हें शुरू करता है. हालांकि, यह व्यू के कॉन्टेंट को नहीं भरता है.ViewHolder
को अब तक किसी खास डेटा से नहीं जोड़ा गया है.onBindViewHolder()
:RecyclerView
इस तरीके को कॉल करके, डेटा के साथViewHolder
को जोड़ता है. यह तरीका, सही डेटा फ़ेच करता है और इसका इस्तेमाल व्यू होल्डर के लेआउट में डेटा भरने के लिए करता है. उदाहरण के लिए, अगरRecyclerView
नामों की सूची दिखाता है, तो यह तरीका सूची में मौजूद सही नाम ढूंढ सकता है. साथ ही, व्यू होल्डर केTextView
विजेट में उस नाम को भर सकता है.getItemCount()
:RecyclerView
इस तरीके को कॉल करके, डेटासेट का साइज़ पता करता है. उदाहरण के लिए, पता पुस्तिका वाले ऐप्लिकेशन में, यह पतों की कुल संख्या हो सकती है. RecyclerView इसका इस्तेमाल यह पता लगाने के लिए करता है कि अब कोई ऐसा आइटम नहीं है जिसे दिखाया जा सकता है.
यहां एक सामान्य अडैप्टर का उदाहरण दिया गया है. इसमें नेस्ट किया गया ViewHolder
है, जो डेटा की सूची दिखाता है. इस मामले में, RecyclerView टेक्स्ट एलिमेंट की एक सामान्य सूची दिखाता है. अडैप्टर को स्ट्रिंग की एक ऐसी ऐरे पास की जाती है जिसमें ViewHolder
एलिमेंट के लिए टेक्स्ट होता है.
Kotlin
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
Java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
हर व्यू आइटम का लेआउट, सामान्य तरीके से एक्सएमएल लेआउट फ़ाइल में तय किया जाता है.
इस मामले में, ऐप्लिकेशन में इस तरह की text_row_item.xml
फ़ाइल है:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
अगले चरण
नीचे दिए गए कोड स्निपेट में, RecyclerView
का इस्तेमाल करने का तरीका बताया गया है.
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
लाइब्रेरी में, लागू करने के तरीके को अपनी पसंद के मुताबिक बनाने के कई विकल्प भी मिलते हैं. ज़्यादा जानकारी के लिए, Advanced RecyclerView को पसंद के मुताबिक बनाने की सुविधा देखें.
एज-टू-एज डिसप्ले की सेटिंग चालू करें
RecyclerView
के लिए, एज-टू-एज डिसप्ले की सेटिंग चालू करने के लिए यह तरीका अपनाएं:
enableEdgeToEdge()
को कॉल करके, पुराने सिस्टम के साथ काम करने वाला एज-टू-एज डिसप्ले सेट अप करें.- अगर सूची के आइटम, सिस्टम बार के साथ ओवरलैप करते हैं, तो
RecyclerView
पर इनसेट लागू करें. इसके लिए,android:fitsSystemWindows
कोtrue
पर सेट करें याViewCompat.setOnApplyWindowInsetsListener
का इस्तेमाल करें. - स्क्रोल करते समय, सूची के आइटम को सिस्टम बार के नीचे दिखाने की अनुमति दें. इसके लिए,
RecyclerView
परandroid:clipToPadding
कोfalse
पर सेट करें.
इस वीडियो में, RecyclerView
पर एज-टू-एज डिसप्ले की सुविधा को बंद (बाईं ओर) और चालू (दाईं ओर) करके दिखाया गया है:
उदाहरण के लिए, इंसर्ट कोड:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener( findViewById(R.id.my_recycler_view) ) { v, insets -> val innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "or WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ) v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom) insets }
Java
ViewCompat.setOnApplyWindowInsetsListener( activity.findViewById(R.id.my_recycler_view), (v, insets) -> { Insets innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "| WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ); v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom ); return insets; } );
RecyclerView
एक्सएमएल:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
अन्य संसाधन
Android पर टेस्टिंग के बारे में ज़्यादा जानने के लिए, यहां दिए गए संसाधन देखें.