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



когда я снова заселяю мой 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-);


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

1027   7  

7 ответов:

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

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

до

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

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

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

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

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

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

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

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

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

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

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

  1. инициализировать arrayList при объявлении его глобально.
  2. добавить список к адаптеру напрямую без проверки на null и пустой ценности. Установите адаптер в список напрямую (не проверяйте наличие состояние.) Адаптер гарантирует вам, что везде, где вы делаете изменения в данных arrayList Он позаботится о нем, но никогда не потеряет ссылка.
  3. всегда изменяйте данные в самом arrayList (если ваши данные совершенно новые чем вы можете назвать adapter.clear() и arrayList.clear() до фактически добавление данных в список), но не устанавливайте адаптер, т. е. если новые данные заполняются в arrayList чем просто adapter.notifyDataSetChanged()

надеюсь, что это помогает.

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

receiptsListView.invalidate().

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

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

у меня была такая же проблема с использованием 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);
}

если 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

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

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

Comments

    Ничего не найдено.