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
添加新列表时。 始终遵守以下准则:
- 在全局声明的同时初始化
arrayList
。 - 直接将列表添加到适配器中,检查空值和空值。 直接将适配器设置到列表中(不要检查任何条件)。 适配器保证,无论你对
arrayList
的数据进行了arrayList
它都会照顾它,但不会松动引用。 - 总是修改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(); } });
添加此代码