it-swarm.com.ru

notifyDataSetChanged не работает из пользовательского адаптера

Когда я заново заполняю свой 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;
    }

}

--Правка:

найден обходной путь

Просто чтобы иметь некоторый функциональный код, который я делаю сейчас:

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

Работает, но не так, как это должно работать.

93
Jasper

Измените свой метод с 

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

К

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

Таким образом, вы сохраняете тот же объект, что и ваш DataSet, в вашем адаптере.

278
tolgap

У меня та же проблема, и я это понимаю. Когда мы создаем адаптер и устанавливаем его в listview, listview будет указывать на объект где-то в памяти, который содержит адаптер, данные этого объекта будут отображаться в listview.

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

если мы снова создадим объект для адаптера с другими данными и notifydatasetchanged ():

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

это не повлияет на данные в просмотре списка, потому что список указывает на другой объект, этот объект ничего не знает о новом объекте в адаптере, и notifyDataSetChanged () не влияет ни на что . Поэтому мы должны изменить данные в объекте и избегать создать новый объект снова для адаптера

22
Nhan Tran

Как я уже объяснил причины этой проблемы, а также как ее решить в другой ветке ответов Здесь . Тем не менее, я делюсь резюме решения здесь.

Одна из главных причин того, что функция notifyDataSetChanged() не будет работать для вас - это, 

Ваш адаптер теряет ссылку на ваш список

При создании и добавлении нового списка в Adapter. Всегда следуйте этим рекомендациям: 

  1. Инициализируйте arrayList, объявив его глобально.
  2. Добавьте список к адаптеру напрямую, не проверяя наличие нулевых и пустых значений Установите адаптер в список напрямую (не проверяйте наличие Условия). Адаптер гарантирует вам, что когда бы вы ни вносили Изменения в данные arrayList, он позаботится об этом, но никогда не потеряет ссылку
  3. Всегда изменяйте данные в самом массиве arrayList (если ваши данные совершенно новые , Чем вы можете вызвать adapter.clear() и arrayList.clear() до Фактического добавления данных в список), но не устанавливайте адаптер, т. Е. Если Новый данные заполняются в arrayList, чем просто adapter.notifyDataSetChanged()

Надеюсь это поможет.

11
Sazzad Hissain Khan

Может быть, попробуйте обновить ваш ListView:

receiptsListView.invalidate().

Правка: Еще одна мысль пришла мне в голову. Просто для записи попробуйте отключить кеш представления списка:

<ListView
    ...
    Android:scrollingCache="false"
    Android:cacheColorHint="@Android:color/transparent"
    ... />
3
Rafal Gałka

У меня была та же проблема с использованием ListAdapter

Я позволил Android Studio реализовать методы для меня, и вот что я получил:

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);
}
3
Davor Zlotrg

Если для 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
Prabs
class StudentAdapter extends BaseAdapter {
    ArrayList<LichHocDTO> studentList;

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

Ты можешь попробовать. Это работает для меня

0
Dũng Phạm Tiến

Добавить этот код

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

У меня та же проблема, но я только что закончил !!

вы должны измениться на

открытый класс 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
林權章