notifyDataSetChange কাস্টম অ্যাডাপ্টার থেকে কাজ করছে না


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 , হাই জ্যাস্পার দয়া করে এই লিঙ্কটি উল্লেখ করুন ... এটি আপনাকে সাহায্য করবে।
তুষার পান্ডে

notifyItemInsert, notifyItemRemoved ইত্যাদির মতো অন্যান্য পদ্ধতির চেষ্টা করুন
রিজেশ পিকে

উত্তর:


334

থেকে আপনার পদ্ধতিটি পরিবর্তন করুন

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

প্রতি

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

সুতরাং আপনি আপনার অ্যাডাপ্টারে আপনার ডেটাসেটের মতো একই জিনিস রাখবেন।


কোনও অবজেক্টের ReceiptListObjectপরিবর্তে প্যারেন্ট অবজেক্ট থাকার কথা বিবেচনা করুন List, এই সমস্যাটি সমাধান করার জন্য আপনি তখন কী করতে পারেন?
85

@ prom85 অ্যারেএডাপ্টারগুলি এমনকি তালিকা বা অ্যারে বাদে অন্য অবজেক্টের সাথে কী বাঁধতে পারে? আমি জানতাম না.
টোলগ্যাপ

এটি একটি সম্পর্কে BaseAdapterএবং এই অ্যাডাপ্টারটি কোন ডাটাতে বাঁধা আছে তা জানে না ... সুতরাং যদি আমার কাছে একটি কাস্টম অবজেক্ট থাকে এবং এই অবজেক্টের কাস্টম ফাংশনগুলি ব্যবহার করা হয় (যেমন custObject.getCount()এবং custObject.getChildAt(int i)উদাহরণস্বরূপ), এবং আমি এই অবজেক্টটি এক্সচেঞ্জ করতে চাই, notifyDataSetChangedকাজ করছে না ... যাহাই হউক না কেন, আমি মনে করি এই সমস্যা একটি সঙ্গে ঘটতে না করেArrayAdapter
prom85

3
আপনি সম্ভবত ব্যাখ্যা করতে পারেন কেন প্রথম পদ্ধতিটি কাজ করে না এবং দ্বিতীয়টি বেসএডাপ্টার দিয়ে কাজ করে?
টুরূপ

1
থ্যাঙ্কস বা +1 এর মত মন্তব্যের অনুমতি নেই তবে কিছু উত্তরে আমি সত্যিই ধন্যবাদ দিতে চাই :)
মুহাম্মদ সাকিব

24

আমারও একই সমস্যা আছে এবং আমি বুঝতে পারি। যখন আমরা অ্যাডাপ্টার তৈরি করি এবং এটিকে তালিকায় রাখি তখন তালিকাগুলি মেমরির কোথাও অবজেক্টকে নির্দেশ করবে যা অ্যাডাপ্টারটি ধারণ করে, এই বস্তুর ডেটা তালিকাভিউতে প্রদর্শিত হবে।

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

যদি আমরা আবার অন্য ডেটা দিয়ে অ্যাডাপ্টারের জন্য একটি অবজেক্ট তৈরি করি এবং বিজ্ঞপ্তি-ডেডেসেটচেঞ্জড ():

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

এটি তালিকায় থাকা ডেটাগুলিতে প্রভাব ফেলবে না কারণ তালিকাটি বিভিন্ন বস্তুর দিকে নির্দেশ করছে, এই বস্তুটি অ্যাডাপ্টারে নতুন অবজেক্ট সম্পর্কে কিছুই জানে না এবং নোটিফাইডাটাসেট চেঞ্জড () কিছুই প্রভাবিত করে না। সুতরাং আমাদের অবজেক্টে ডেটা পরিবর্তন করা উচিত এবং অ্যাডাপ্টারের জন্য আবার একটি নতুন অবজেক্ট তৈরি করা এড়ানো উচিত


10
আপনি অ্যাডাপ্টার বস্তুটি পুনরায় তৈরি করছেন, এটি কার্যকর নয়
আলেজিস

2
@ আলেজিস আমি মনে করি ঠিক এটাই বোঝা যাচ্ছিল নান।
নীরজ শেওয়ানি

17

আমি ইতিমধ্যে এই সমস্যা পিছনে কারণ এবং কিভাবে একটি ভিন্ন উত্তর থ্রেড এটা হ্যান্ডেল করতে ব্যাখ্যা হিসাবে এখানে । তবুও আমি সমাধানের সারাংশ এখানে ভাগ করছি।

অন্যতম প্রধান কারণ আপনার notifyDataSetChanged()পক্ষে কাজ করবে না - হ'ল

আপনার অ্যাডাপ্টার আপনার তালিকার রেফারেন্স হারায়

একটি নতুন তালিকা তৈরি এবং যুক্ত করার সময় Adapter । সর্বদা এই নির্দেশিকা অনুসরণ করুন:

  1. শুরু arrayListএটি বিশ্বব্যাপী ঘোষণা সময় ।
  2. নাল এবং ফাঁকা মান পরীক্ষা করে সরাসরি অ্যাডাপ্টারে তালিকা যুক্ত করুন। সরাসরি তালিকায় অ্যাডাপ্টার সেট করুন (কোনও শর্তের জন্য পরীক্ষা করবেন না)। অ্যাডাপ্টার আপনাকে গ্যারান্টি দেয় যে আপনি যেখানেই তথ্যের ডেটাতে পরিবর্তন করেনarrayList এটি তার যত্ন নেবে, তবে রেফারেন্সটি কখনই ছাড়বে না।
  3. সর্বদা arrayList নিজেই ডেটা সংশোধন (যদি আপনার ডেটা সম্পূর্ণ নতুন চেয়ে আপনি কল করতে পারেন adapter.clear()এবং arrayList.clear()সামনে আসলে লিস্টে তথ্য যোগ) কিন্তু সেট না অ্যাডাপ্টারের অর্থাত নতুন তথ্য জনবহুল হয়, তাহলেarrayList শুধু চেয়ে adapter.notifyDataSetChanged()

আশাকরি এটা সাহায্য করবে.


1
ধন্যবাদ! # 2 এ টিপ সাহায্য করেছে।
চেরুবি

4

আপনার লিস্টভিউটি রিফ্রেশ করার চেষ্টা করুন:

receiptsListView.invalidate()

সম্পাদনা: আমার মনে আরও একটা চিন্তা এসে গেল। কেবল রেকর্ডের জন্য, তালিকা দর্শন ক্যাশে অক্ষম করার চেষ্টা করুন:

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

অদ্ভুত, আমার শেষ ধারণাটি ডেটা পরিবর্তনের পরে অ্যাডাপ্টারকে তালিকা দর্শনে পুনরায় সাইন করা। তবে আমি মনে করি আপনি ইতিমধ্যে এটি চেষ্টাও করেছেন।
রাফাল গাওকা

3

ব্যবহার করতে আমারও একই সমস্যা ছিল ListAdapter

আমি অ্যান্ড্রয়েড স্টুডিওগুলিকে আমার জন্য পদ্ধতিগুলি প্রয়োগ করতে দিয়েছি এবং এটিই আমি পেয়েছি:

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/autocompletetextview-with-dynamic.html


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

...

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

...

যদিও, আমি একই অ্যাডাপ্টার এবং পুনর্ব্যবহারযোগ্য ভিউয়ের একাধিক উদাহরণ তৈরি করার প্রস্তাব দিই না।



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<>();
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.