Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Android

Android पर ListView का रीसाइक्लिंग मैकेनिज्म कैसे काम करता है?

Android में ListView/RecyclerView रीसाइक्लिंग मैकेनिज्म समझाया गया

यह ट्यूटोरियल बताता है कि Android में व्यू रीसाइक्लिंग कैसे काम करता है - ListView के कन्वर्टव्यू पैटर्न से लेकर RecyclerView के अनिवार्य ViewHolder पैटर्न तक।

रीसाइक्लिंग क्यों जरूरी है?

बिना रीसाइक्लिंग के, 1000 आइटम्स की लिस्ट के लिए 1000 व्यू ऑब्जेक्ट्स बनेंगे - मेमोरी खत्म हो जाएगी और स्क्रॉलिंग लैगी होगी। रीसाइक्लिंग से केवल विजिबल आइटम्स (+ बफर) के व्यू बनते हैं।

ListView का कन्वर्टव्यू पैटर्न (लीगेसी)

// ListView एडाप्टर में getView()
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    
    if (convertView == null) {
        // नया व्यू इन्फ्लेट करें - केवल पहली बार
        convertView = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
        holder = new ViewHolder();
        holder.textView = convertView.findViewById(R.id.textView);
        convertView.setTag(holder);
    } else {
        // मौजूदा व्यू पुनः उपयोग करें
        holder = (ViewHolder) convertView.getTag();
    }
    
    // डेटा बाइंड करें
    holder.textView.setText(getItem(position));
    return convertView;
}

static class ViewHolder {
    TextView textView;
}

RecyclerView का अनिवार्य ViewHolder पैटर्न

RecyclerView में रीसाइक्लिंग अनिवार्य है - कोई कन्वर्टव्यू पैरामीटर नहीं:

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    private List<String> cities;

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // केवल नए ViewHolder बनाएं जब पूल खाली हो
        View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_row, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // केवल डेटा बाइंड करें - व्यू पहले से बना हुआ है
        holder.tvCountry.setText(cities.get(position));
    }

    @Override
    public int getItemCount() {
        return cities.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvCountry;
        ViewHolder(View view) {
            super(view);
            tvCountry = view.findViewById(R.id.tv_country);
        }
    }
}

रीसाइक्लिंग प्रक्रिया विजुअलाइज़ेशन

स्क्रॉल डाउन:
┌─────────────────────────────────────┐
│ Item 0 (विजिबल)                    │  → स्क्रॉल आउट → रीसाइक्लर पूल में जाता है
│ Item 1 (विजिबल)                    │
│ Item 2 (विजिबल)                    │
│ Item 3 (विजिबल)                    │
│ Item 4 (आंशिक)                     │
└─────────────────────────────────────┘
           ↓ यूजर स्क्रॉल करता है ↓
┌─────────────────────────────────────┐
│ Item 1 (विजिबल)                    │
│ Item 2 (विजिबल)                    │
│ Item 3 (विजिबल)                    │
│ Item 4 (विजिबल)                    │
│ Item 5 (नया - पूल से रीसाइक्ल्ड व्यू) │  ← Item 0 का व्यू पुनः उपयोग हुआ
└─────────────────────────────────────┘

चरण 1-6: पूरा उदाहरण (RecyclerView के साथ)

कार्ड रो लेआउट res/layout/card_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">
    <TextView
        android:id="@+id/tv_country"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginVertical="10dp"
        android:textSize="18sp"
        android:textStyle="bold" />
</androidx.cardview.widget.CardView>

MainActivity src/MainActivity.java:

package com.app.sample;

import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private ArrayList<String> cities;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        RecyclerView recyclerView = findViewById(R.id.card_recycler_view);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        
        cities = new ArrayList<>();
        cities.add("मुंबई");
        cities.add("चेन्नई");
        cities.add("कोच्चि");
        cities.add("बेंगलुरु");
        cities.add("हैदराबाद");
        cities.add("अमरावती");
        cities.add("गोवा");
        cities.add("तिरुवनंतपुरम");
        cities.add("कोयंबटूर");
        cities.add("वेल्लोर");
        cities.add("सेलम");
        cities.add("भुवनेश्वर");
        cities.add("कटक");
        cities.add("मैसूर");
        
        DataAdapter adapter = new DataAdapter(cities);
        recyclerView.setAdapter(adapter);
        
        // आइटम क्लिक हैंडलिंग
        recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            GestureDetector gestureDetector = new GestureDetector(getApplicationContext(), 
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onSingleTapUp(MotionEvent e) { return true; }
                });
            
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                View child = rv.findChildViewUnder(e.getX(), e.getY());
                if (child != null && gestureDetector.onTouchEvent(e)) {
                    int position = rv.getChildAdapterPosition(child);
                    Toast.makeText(getApplicationContext(), 
                        "चुना गया: " + cities.get(position), Toast.LENGTH_SHORT).show();
                }
                return false;
            }
            @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
            @Override public void onRequestDisallowInterceptTouchEvent(boolean disallow) {}
        });
    }
}

DataAdapter src/DataAdapter.java:

package com.app.sample;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    private ArrayList<String> cities;

    public DataAdapter(ArrayList<String> cities) {
        this.cities = cities;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_row, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.tvCountry.setText(cities.get(position));
    }

    @Override
    public int getItemCount() {
        return cities.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvCountry;
        ViewHolder(View view) {
            super(view);
            tvCountry = view.findViewById(R.id.tv_country);
        }
    }
}

आधुनिक बेहतरी: ListAdapter + DiffUtil

public class ModernAdapter extends ListAdapter<String, ModernAdapter.ViewHolder> {
    public ModernAdapter() {
        super(new DiffUtil.ItemCallback<String>() {
            @Override
            public boolean areItemsTheSame(@NonNull String old, @NonNull String newItem) {
                return old.equals(newItem);
            }
            @Override
            public boolean areContentsTheSame(@NonNull String old, @NonNull String newItem) {
                return old.equals(newItem);
            }
        });
    }
    // ... ViewHolder और बाइंडिंग
}

रीसाइक्लिंग के लिए बेस्ट प्रैक्टिसेज

  • onCreateViewHolder में न्यूनतम काम करें - केवल इन्फ्लेट और findViewById
  • onBindViewHolder में केवल डेटा सेट करें - लेआउट पैरामीटर्स न बदलें
  • setHasFixedSize(true) सेट करें अगर आइटम साइज फिक्स्ड है
  • पेलोड्स के साथ notifyItemChanged() उपयोग करें आंशिक अपडेट के लिए
  • ViewHolder में महंगे ऑब्जेक्ट्स कैश करें - इमेज लोडर, फॉर्मेटर्स
  • RecyclerView.RecycledViewPool शेयर करें एक्टिविटीज के बीच

आम गलतियां

गलतीसमस्यासमाधान
onBindViewHolder में findViewByIdपरफॉरमेंस हिटViewHolder में कैश करें
पोजीशन के आधार पर लेआउट पैरामीटर्स बदलनारीसाइक्लिंग बग्सलेआउट XML में हैंडल करें
notifyDataSetChanged() ओवरयूजनो एनिमेशन, फुल रीबाइंडस्पेसिफिक notifyItem* मेथड्स
एसिंक ऑपरेशन में पोजीशन उपयोग करनागलत डेटा बाइंडिंगgetAdapterPosition() या होल्डर टैग उपयोग करें
  1. Android में ListView के लिए कस्टम एडाप्टर कैसे बनाएं? Android में ListView के लिए कस्टम एडाप्टर कैसे बनाएं?

    Android ListView के लिए कस्टम एडाप्टर बनाना यह उदाहरण दर्शाता है कि BaseAdapter को एक्सटेंड करके कस्टम एडाप्टर कैसे बनाया जाए, जो कस्टम डेटा मॉडल और कस्टम रो लेआउट के साथ ListView में डेटा बाइंड करता है। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project चुनें। चरण 2: मेन लेआउट (res/

  1. एंड्रॉइड में डायनामिकली बटन कैसे जोड़ें? एंड्रॉइड में डायनामिकली बटन कैसे जोड़ें?

    एंड्रॉइड में रनटाइम पर प्रोग्रामेटिकली बटन (या कोई व्यू) जोड़ना कभी-कभी लेआउट XML में नहीं, बल्कि डेटा/शर्तों के आधार पर रनटाइम पर व्यूज जोड़ने पड़ते हैं। इसके लिए: **पैरेंट व्यूग्रुप प्राप्त करें → नया व्यू बनाएं → LayoutParams सेट करें → addView() कॉल करें।** चरण 1: नया प्रोजेक्ट बनाएं Android St

  1. Android में डेटाबेस से CheckBox को ListView में कैसे बाइंड करें? Android में डेटाबेस से CheckBox को ListView में कैसे बाइंड करें?

    यह उदाहरण दर्शाता है कि Android में डेटाबेस (या डेटा सोर्स) से डेटा लेकर CheckBox वाले ListView में कैसे बाइंड किया जाता है। कस्टम एडॉप्टर और व्यू होल्डर पैटर्न का उपयोग किया गया है। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project। चरण 2: मेन लेआउट res/layout/activity_main.xml: &l