Adapter.notifyDataSetChanged()数据改变却不刷新的原因

今天做Android作业的时候发现个现象:

List<SongVO> mSongVOs = getSongs(A);//数据A
SongAdapter mSongAdapter = new SongAdapter(getApplicationContext(), mSongVOs);//用数据初始化适配器
lvMusicList.setAdapter(mSongAdapter);//为ListView绑定适配器

//情况1.可以刷新Listview数据
mSongVOs.remove(x);
mSongAdapter.notifyDataSetChanged();

//情况2.不刷新
mSongVOs=getSongs(B);//数据B
mSongAdapter.notifyDataSetChanged();

//情况3.可以刷新
mSongVOs.clear();
mSongVOs.addAll(helper.getAudios());
mSongAdapter.notifyDataSetChanged();

摸索了一下,找到了原因:
查看SongAdapter的构造函数:

public class SongAdapter extends BaseAdapter {

    private List<SongVO> mData;
    private Context mContext;

    public SongAdapter(Context context, List<SongVO> songs) {
        mContext = context;
        mData = songs;
    }

    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }
    ...
}

Adapter通常的写法都是用一个成员变量mData持有着对数据的引用,之后ListView的刷新都是通过Adapter.getItem()等方法进行更新,而这些方法访问的数据时这个mData指向的数据。如果这个数据不变,那么notifyDataSetChanged自然不会刷新。

在情况1、3中,局部变量mSongVOs和SongAdapter的成员变量mData指向的是同一块内存地址,即数据A,因此mSongVOs修改A后,notifyDataSetChanged通过mData再访问A时发现数据变了,所以就更新了ListView。
在情况2中,局部变量mSongVOs通过getSong(B)获取新数据B,实际是mSongVOs指向了内存中另外一块地址B,而此时mData指向的仍然是A。因此notifyDataSetChanged观察到A始终没有变化,因此不刷新。

所以,情况2,并不是Adapter“数据变了却不刷新”,而是“数据根本没变”。
而网上说重新对adapter绑定即可刷新,实际上就是重新绑定了成员变量mData,因此可以刷新。

情况2、3的业务逻辑是换了一整批数据,编程上情况2似乎是很直观和合理的,但是得注意了,得用第三种写法。

再次论内存分析的重要性!

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值