notifyDataSetChange不能从自定义适配器工作

当我重新填充我的ListView ,我从我的Adapter调用一个特定的方法。

问题

当我从我的Adapter调用updateReceiptsList ,数据刷新,但我的ListView不反映更改。

问题

为什么当我调用notifyDataSetChanged时,我的ListView显示新的数据?

适配器

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

– 编辑:

find解决方法

只是为了让我现在有一些function的代码:

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

工作,但不是它应该如何工作。

改变你的方法

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

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

所以你保持与你的DataSet相同的对象在你的适配器。

我有同样的问题,我意识到这一点。 当我们创build适配器并将其设置为listview时,listview将指向对象中某个适配器所在的内存,此对象中的数据将在listview中显示。

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

如果我们再次为另一个数据创build一个适配器对象,并且notifydatasetchanged():

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

这将不会影响到listview中的数据,因为列表指向不同的对象,这个对象不知道什么关于适配器中的新对象,并且notifyDataSetChanged()不影响任何内容。 所以我们应该改变对象中的数据,并避免为适配器再次创build一个新的对象

正如我已经解释了这个问题背后的原因,以及如何处理它在不同的答案线程在这里 。 我仍然在这里分享解决scheme总结。

notifyDataSetChanged()主要原因之一不会为你工作 – 是的,

您的适配器失去对您的列表的引用

创build并向Adapter添加新列表时。 始终遵守以下准则:

  1. 在全局声明的同时初始化arrayList
  2. 直接将列表添加到适配器中,检查空值和空值。 直接将适配器设置到列表中(不要检查任何条件)。 适配器保证,无论你对arrayList的数据进行了arrayList它都会照顾它,但不会松动引用。
  3. 总是修改arrayList本身的数据(如果你的数据是完全新的,你可以在实际向列表中添加数据之前调用adapter.clear()arrayList.clear() ),但是不要设置适配器。如果新数据被填充在arrayList而不仅仅是adapter.notifyDataSetChanged()

希望这可以帮助。

也许尝试刷新您的ListView:

receiptsListView.invalidate()

编辑:另一个想法进入我的脑海。 只是为了logging,尝试禁用列表视图caching:

 <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); } 
 runOnUiThread(new Runnable() { public void run() { adapter = new CustomAdapter(anotherdata); adapter.notifyDataSetChanged(); } }); 

添加此代码