notifyDataSetChange无法使用自定义适配器

Jas*_*per 114 android listview baseadapter 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

- 编辑:

找到解决方法

我现在要做一些功能代码:

listview.setAdapter( new ReceiptListAdapter(activity,mcontext, -new dataset-);
Run Code Online (Sandbox Code Playgroud)

工作,但不是如何工作.

tol*_*gap 307

改变你的方法

public void updateReceiptsList(List<Receipt> newlist) {
    receiptlist = newlist;
    this.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

public void updateReceiptsList(List<Receipt> newlist) {
    receiptlist.clear();
    receiptlist.addAll(newlist);
    this.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

因此,您在适配器中保留与DataSet相同的对象.

  • 您能否解释为什么第一种方法不起作用,而第二种方法对BaseAdapter起作用? (2认同)
  • 不允许发表诸如“谢谢”或“+1”之类的评论,但对于某些答案,我真的很想表示感谢:) (2认同)

Nha*_*ran 22

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

adapter = new CustomAdapter(data);
listview.setadapter(adapter);
Run Code Online (Sandbox Code Playgroud)

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

adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();
Run Code Online (Sandbox Code Playgroud)

这不会影响listview中的数据,因为列表指向不同的对象,此对象对适配器中的新对象一无所知,而notifyDataSetChanged()不会影响任何内容.因此我们应该更改对象中的数据,并避免再次为适配器创建新对象

  • 你正在重新创建适配器对象,它效率不高 (9认同)
  • @Alezis 我认为这正是 Nhan 的意思。 (3认同)

Saz*_*han 14

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

其中一个主要原因notifyDataSetChanged()对你不起作用 - 是的,

您的适配器丢失对您的列表的引用.

在创建和添加新列表时Adapter.始终遵循以下准则:

  1. 初始化arrayListwhile同时在全局声明它.
  2. 直接将List添加到适配器,不检查null和空值.直接将适配器设置为列表(不检查任何条件).适配器保证您无论何时对其数据进行更改arrayList都会照顾它,但绝不会丢失引用.
  3. 随时修改ArrayList中本身的数据(如果你的数据完全是新的比你可以打电话adapter.clear()arrayList.clear()之前实际上将数据添加到列表中),但不设置适配器,即如果新的数据是在人口arrayList不仅仅是 adapter.notifyDataSetChanged()

希望这可以帮助.