कस्टम एडेप्टर से काम नहीं कर रहा है


125

जब मैं अपने को फिर से खोल देता हूं ListView, तो मैं अपनी ओर से एक विशिष्ट विधि कहता हूं Adapter

समस्या :

जब मैं updateReceiptsListअपने से कॉल करता हूं Adapter, तो डेटा रीफ्रेश हो जाता है, लेकिन मेरा ListViewपरिवर्तन नहीं दिखता है।

प्रश्न :

ListViewजब मैं कॉल करता हूं तो मेरा नया डेटा क्यों नहीं दिखाता है notifyDataSetChanged?

एडाप्टर :

public class ReceiptListAdapter extends BaseAdapter {

    public List<Receipt> receiptlist;
    private Context context;
    private LayoutInflater inflater;
    private DateHelpers dateH;

    public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) {
        context = mcontext;
        receiptlist = rl;
        Collections.reverse(receiptlist);
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        dateH = new DateHelpers();
    }

    @Override
    public int getCount() {
        try {
            int size = receiptlist.size();
            return size;
        } catch(NullPointerException ex) {
            return 0;
        }
    }

    public void updateReceiptsList(List<Receipt> newlist) {
        receiptlist = newlist;
        this.notifyDataSetChanged();
    }

    @Override
    public Receipt getItem(int i) {
        return receiptlist.get(i);
    }

    @Override
    public long getItemId(int i) {
        return receiptlist.get(i).getReceiptId() ;
    }

    private String getPuntenString(Receipt r) {
        if(r.getPoints().equals("1")) {
            return "1 punt";
        }
        return r.getPoints()+" punten";
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;

        final Receipt receipt = receiptlist.get(position);
        ReceiptViewHolder receiptviewholder;
        Typeface tf_hn = Typeface.createFromAsset(context.getAssets(), "helveticaneue.ttf");        
        Typeface tf_hn_bold = Typeface.createFromAsset(context.getAssets(), "helveticaneuebd.ttf");

        if (vi == null) { //convertview==null
            receiptviewholder = new ReceiptViewHolder();
            vi = inflater.inflate(R.layout.view_listitem_receipt, null);
            vi.setOnClickListener(null);
            vi.setOnLongClickListener(null);
            vi.setLongClickable(false);
            receiptviewholder.shop = (TextView) vi.findViewById(R.id.tv_listitemreceipt_shop);
            receiptviewholder.date = (TextView) vi.findViewById(R.id.tv_listitemreceipt_date);
            receiptviewholder.price = (TextView) vi.findViewById(R.id.tv_listitemreceipt_price);
            receiptviewholder.points = (TextView) vi.findViewById(R.id.tv_listitemreceipt_points);
            receiptviewholder.shop.setTypeface(tf_hn_bold);
            receiptviewholder.price.setTypeface(tf_hn_bold);
            vi.setTag(receiptviewholder);
        }else{//convertview is not null
            receiptviewholder = (ReceiptViewHolder)vi.getTag();
        }

        receiptviewholder.shop.setText(receipt.getShop());
        receiptviewholder.date.setText(dateH.timestampToDateString(Long.parseLong(receipt.getPurchaseDate())));
        receiptviewholder.price.setText("€ "+receipt.getPrice());
        receiptviewholder.points.setText(getPuntenString(receipt));

        vi.setClickable(false);
        return vi;
    }

    public static class ReceiptViewHolder {
        public TextView shop;
        public TextView date;
        public TextView price;
        public TextView points;
    }

    public Object getFilter() {
        // XXX Auto-generated method stub
        return null;
    }

}

--EDIT:

वर्कअराउंड मिला

बस मेरे पास अभी कुछ कार्यात्मक कोड होने के लिए:

listview.setAdapter( new ReceiptListAdapter(activity,mcontext, -new dataset-);

काम करता है, लेकिन यह नहीं है कि यह कैसे काम करना चाहिए।


stackoverflow.com/a/4198569/2382964 , हाय जैस्पर कृपया इस लिंक को देखें ... इससे आपको मदद मिलेगी।
तुषार पांडे

अन्य तरीकों की कोशिश करें जैसे कि InformItemInserted, InformItemRemoved, आदि ..
Reejesh PK

जवाबों:


334

से अपना तरीका बदलें

public void updateReceiptsList(List<Receipt> newlist) {
    receiptlist = newlist;
    this.notifyDataSetChanged();
}

सेवा

public void updateReceiptsList(List<Receipt> newlist) {
    receiptlist.clear();
    receiptlist.addAll(newlist);
    this.notifyDataSetChanged();
}

तो आप अपने एडेप्टर में अपने DataSet के समान ऑब्जेक्ट रखें।


वस्तुओं के ReceiptListObjectबजाय माता-पिता की वस्तु होने पर विचार Listकरें, फिर आप इस समस्या को हल करने के लिए क्या कर सकते हैं?
Prom85

@ prom85 ArrayAdapters को भी सूचियों या Arrays के अलावा अन्य वस्तुओं से बाँध सकते हैं? मुझे नहीं पता था।
tolgap

यह एक के बारे में है BaseAdapterऔर यह एडॉप्टर यह नहीं जानता है कि यह किस डेटा से जुड़ा हुआ है ... इसलिए यदि मेरे पास कोई कस्टम ऑब्जेक्ट है और इस ऑब्जेक्ट के कस्टम फ़ंक्शंस (जैसे custObject.getCount()और custObject.getChildAt(int i)उदाहरण के लिए) का उपयोग करता है, और मैं इस ऑब्जेक्ट का आदान-प्रदान करना चाहता हूं, notifyDataSetChangedतो यह काम नहीं कर रहा है ... वैसे भी, मुझे लगता है कि यह समस्या कभी नहीं होती हैArrayAdapter
प्रॉम 85

3
क्या आप शायद समझा सकते हैं कि पहला तरीका काम क्यों नहीं करता है और दूसरा बेस एडेप्टर के साथ काम करता है?
थोरोपॉप

1
धन्यवाद या +1 जैसी टिप्पणियों की अनुमति नहीं है, लेकिन कुछ उत्तरों पर मैं वास्तव में धन्यवाद देना चाहता हूं :)
मुहम्मद साकिब

24

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

adapter = new CustomAdapter(data);
listview.setadapter(adapter);

यदि हम फिर से एक और डेटा के साथ एडेप्टर के लिए ऑब्जेक्ट बनाते हैं और Informdatasetchanged ():

adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();

यह सूची में डेटा को प्रभावित नहीं करेगा क्योंकि सूची अलग-अलग ऑब्जेक्ट को इंगित कर रही है, यह ऑब्जेक्ट एडेप्टर में नई ऑब्जेक्ट के बारे में कुछ भी नहीं जानता है, और InformDataSetChanged () कुछ भी प्रभावित नहीं करता है। इसलिए हमें ऑब्जेक्ट में डेटा बदलना चाहिए और एडॉप्टर के लिए फिर से एक नया ऑब्जेक्ट बनाने से बचना चाहिए


10
आप एडॉप्टर ऑब्जेक्ट को फिर से बना रहे हैं, यह कुशल नहीं है
एलेज़िस

2
@ एलेजिस मुझे लगता है कि वास्तव में नाहन का यही मतलब है।
नीरज सेवानी

17

मैं पहले से ही इस मुद्दे के पीछे के कारणों और यह भी कि कैसे एक अलग जवाब सूत्र में इसे संभाल करने के लिए समझा दिया है के रूप में यहाँ । फिर भी मैं यहां समाधान सारांश साझा कर रहा हूं।

मुख्य कारणों में notifyDataSetChanged()से एक आप के लिए काम नहीं करेगा - है,

आपका एडाप्टर आपकी सूची का संदर्भ खो देता है

जब एक नई सूची बनाते और जोड़ते हैं Adapter। हमेशा इन दिशानिर्देशों का पालन करें:

  1. शुरुआत में arrayListइसे वैश्विक स्तर पर घोषित करते हुए।
  2. नल और खाली मानों के लिए चेक आउट के साथ सीधे एडाप्टर में सूची जोड़ें। एडाप्टर को सीधे सूची पर सेट करें (किसी भी स्थिति के लिए जांच न करें)। एडेप्टर आपको गारंटी देता है कि जहां भी आप इसके डेटा में बदलाव arrayListकरेंगे, उसका ध्यान रखेंगे, लेकिन संदर्भ को कभी ढीला न करें।
  3. हमेशा सरणी में डेटा को संशोधित करें (यदि आपका डेटा पूरी तरह से नया है जिसे आप कॉल कर सकते हैं adapter.clear()और arrayList.clear()वास्तव में सूची में डेटा जोड़ने से पहले) लेकिन एडॉप्टर सेट न करें अर्थात यदि नया डेटा arrayListकेवल से अधिक में पॉपुलेटेड हैadapter.notifyDataSetChanged()

उम्मीद है की यह मदद करेगा।


1
धन्यवाद! # 2 पर टिप ने मदद की।
चेरुबी

4

शायद अपने ListView को ताज़ा करने का प्रयास करें:

receiptsListView.invalidate()

संपादित करें: मेरे दिमाग में एक और विचार आया। केवल रिकॉर्ड के लिए, सूची दृश्य कैश अक्षम करने का प्रयास करें:

<ListView
    ...
    android:scrollingCache="false"
    android:cacheColorHint="@android:color/transparent"
    ... />

अजीब, डेटा बदलने के बाद दृश्य को सूचीबद्ध करने के लिए एडेप्टर को पुन: असाइन करने के लिए मेरा अंतिम विचार है। लेकिन मुझे लगता है कि आपने पहले ही यह कोशिश की थी।
रफाल गल्का

3

मैं एक ही समस्या का उपयोग कर रहा था ListAdapter

मैंने Android स्टूडियो को मेरे लिए तरीके लागू करने दिए और मुझे यही मिला:

public class CustomAdapter implements ListAdapter {
    ...
    @Override
    public void registerDataSetObserver(DataSetObserver observer) {

    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {

    }
    ...
}

समस्या यह है कि ये विधियाँ superकार्यान्वयन को नहीं कहते हैंnotifyDataSetChange इसे कभी नहीं बुलाया जाता है।

या तो इन ओवरराइड्स को मैन्युअल रूप से हटा दें या सुपर कॉल्स जोड़ें और इसे फिर से काम करना चाहिए।

@Override
public void registerDataSetObserver(DataSetObserver observer) {
    super.registerDataSetObserver(observer);
}

@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
    super.unregisterDataSetObserver(observer);
}

2
class StudentAdapter extends BaseAdapter {
    ArrayList<LichHocDTO> studentList;

    private void capNhatDuLieu(ArrayList<LichHocDTO> list){
        this.studentList.clear();
        this.studentList.addAll(list);
        this.notifyDataSetChanged();
    }
}

तुम कोशिश कर सकते हो। यह मेरे लिए काम करता है


1

अगर adapterसेट है AutoCompleteTextViewतो notifyDataSetChanged()काम नहीं करता है।

एडॉप्टर अपडेट करने के लिए इसकी आवश्यकता है:

myAutoCompleteAdapter = new ArrayAdapter<String>(MainActivity.this, 
        android.R.layout.simple_dropdown_item_1line, myList);

myAutoComplete.setAdapter(myAutoCompleteAdapter);

संदर्भ: http://android-er.blogspot.in/2012/10/autocompletetextext


1

किसी भी संयोग से यदि आप इस धागे पर उतरा और सोच तो क्यों adapter.invaidate()या adapter.clear()क्योंकि आप उपयोग कर रहे हैं तरीकों तो शायद अपने मामले में मौजूद नहीं हैं RecyclerView.Adapterके बजाय BaseAdapterजो इस सवाल का प्रश्नकर्ता द्वारा प्रयोग किया जाता है। समाशोधन हैं listया arraylistनहीं अपनी समस्या को हल करने तो यह हो सकता है कि आप कर रहे हैं दो या अधिक उदाहरण के adapterपूर्व के लिए .:

मुख्य गतिविधि

...

adapter = new CustomAdapter(list);
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);

...

और
कुछ

...

adapter = new CustomAdapter(newList);
adapter.notifyDataSetChanged();

...

यदि दूसरे मामले में आप पुनर्नवीनीकरण दृश्य में फुलाए गए विचारों की सूची में बदलाव की उम्मीद कर रहे हैं, तो ऐसा होने वाला नहीं है क्योंकि दूसरी बार में एक नया उदाहरण adapterबनाया गया है जो कि पुनर्नवीनीकरण दृश्य से जुड़ा नहीं है। notifyDataSetChangedदूसरे एडेप्टर में सेटिंग करने से रिसाइकल व्यू का कंटेंट बदलने वाला नहीं है। इसके लिए SomeFragment में पुनर्नवीनीकरण दृश्य का एक नया उदाहरण बनाएं और इसे एडेप्टर के नए उदाहरण से संलग्न करें।

SomeFragment

...

recyclerView = new RecyclerView();
adapter = new CustomAdapter();
recyclerView.setAdapter(adapter);

...

हालाँकि, मैं एक ही एडेप्टर और रिसाइकलर व्यू के कई उदाहरण बनाने की सलाह नहीं देता।


0

इस कोड को जोड़ें

runOnUiThread(new Runnable() { public void run() {
               adapter = new CustomAdapter(anotherdata);
            adapter.notifyDataSetChanged();
            }
        });

0

मैं एक ही समस्या है, लेकिन मैं इसे खत्म कर दिया !!

आपको बदलना चाहिए

public class ReceiptListAdapter extends BaseAdapter {

    public List<Receipt> receiptlist;
    private Context context;
    private LayoutInflater inflater;
    private DateHelpers dateH;
    private List<ReceiptViewHolder> receiptviewlist;

    public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) {
        context = mcontext;
        receiptlist = rl;
        receiptviewlist = new ArrayList<>();
        receiptviewlist.clear();
        for(int i = 0; i < receiptlist.size(); i++){
          ReceiptViewHolder receiptviewholder = new ReceiptViewHolder();
          receiptviewlist.add(receiptviewholder);
        }
        Collections.reverse(receiptlist);
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        dateH = new DateHelpers();
    }

    @Override
    public int getCount() {
        try {
            int size = receiptlist.size();
            return size;
        } catch(NullPointerException ex) {
            return 0;
        }
    }

    public void updateReceiptsList(List<Receipt> newlist) {
        receiptlist = newlist;
        this.notifyDataSetChanged();
    }

    @Override
    public Receipt getItem(int i) {
        return receiptlist.get(i);
    }

    @Override
    public long getItemId(int i) {
        return receiptlist.get(i).getReceiptId() ;
    }

    private String getPuntenString(Receipt r) {
        if(r.getPoints().equals("1")) {
            return "1 punt";
        }
        return r.getPoints()+" punten";
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;

        final Receipt receipt = receiptlist.get(position);
        ReceiptViewHolder receiptviewholder;
        Typeface tf_hn = Typeface.createFromAsset(context.getAssets(), "helveticaneue.ttf");        
        Typeface tf_hn_bold = Typeface.createFromAsset(context.getAssets(), "helveticaneuebd.ttf");

        if (vi == null) { //convertview==null
            ReceiptViewHolder receiptviewholder = receiptviewlist.get(position);
            vi = inflater.inflate(R.layout.view_listitem_receipt, null);
            vi.setOnClickListener(null);
            vi.setOnLongClickListener(null);
            vi.setLongClickable(false);
            receiptviewholder.shop = (TextView) vi.findViewById(R.id.tv_listitemreceipt_shop);
            receiptviewholder.date = (TextView) vi.findViewById(R.id.tv_listitemreceipt_date);
            receiptviewholder.price = (TextView) vi.findViewById(R.id.tv_listitemreceipt_price);
            receiptviewholder.points = (TextView) vi.findViewById(R.id.tv_listitemreceipt_points);
            receiptviewholder.shop.setTypeface(tf_hn_bold);
            receiptviewholder.price.setTypeface(tf_hn_bold);
            vi.setTag(receiptviewholder);
        }else{//convertview is not null
            receiptviewholder = (ReceiptViewHolder)vi.getTag();
        }

        receiptviewholder.shop.setText(receipt.getShop());
        receiptviewholder.date.setText(dateH.timestampToDateString(Long.parseLong(receipt.getPurchaseDate())));
        receiptviewholder.price.setText("€ "+receipt.getPrice());
        receiptviewholder.points.setText(getPuntenString(receipt));

        vi.setClickable(false);
        return vi;
    }

    public static class ReceiptViewHolder {
        public TextView shop;
        public TextView date;
        public TextView price;
        public TextView points;
    }

    public Object getFilter() {
        // XXX Auto-generated method stub
        return null;
    }

}

0

मेरा मामला अलग था लेकिन दूसरों के लिए भी ऐसा ही हो सकता है

उन लोगों के लिए जो अभी भी एक समाधान नहीं ढूंढ सके और ऊपर सब कुछ करने की कोशिश की, यदि आप एडैप्टर का उपयोग टुकड़े के अंदर कर रहे हैं तो इसका कारण यह काम नहीं कर रहा है fragment could be recreating so the adapter is recreating everytime the fragment recreate

एडाप्ट करने से पहले एडॉप्टर और ऑब्जेक्ट्स की सूची शून्य होने पर आपको सत्यापित करना चाहिए

if(adapter == null){
  adapter = new CustomListAdapter(...);
}
...

if(objects == null){
  objects = new ArrayList<>();
}

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