Android中RecyclerView调用notifyDataSetChanged方法无效

转载请注明出处:http://blog.csdn.net/sinat_14849739/article/details/78483595
本文出自Shawpoo的专栏
我的简书:简书

问题描述

这两天在开发中遇到一个问题,就是很常见的一种情况,定义一个数据的集合List,然后获取到数据(网络或者本地)之后更改List,然后通过RecycerView进行展示,这时候我们通常使用AdapternotifyDataSetChanged()方法来刷新,但是却无效。

下面我大概模拟一下:

private List<Test> mList = new ArrayList<>();  // 定义数据源集合

// 获取到数据进行更新
private void updateData(List<Test> list) {
    mList = list;
    mAdapter.notifyDataSetChanged(); //刷新
}

mList为绑定Adapter的数据源,然后通过updateData()获取到新数据,然后通过 notifyDataSetChanged()进行刷新,然后发现并没有任何效果。

分析

其实这是一个很容易犯的错误,代码很简单,但就是没效果。原因就出在mAdater前后使用的不是一个对象。虽然上面的例子使用的都为mList,看似没有变,实际上在更新数据的时候,直接把返回数据的集合赋值给了mList。难道赋值后就不是同一个集合对象了?

如何证明是不是一个对象呢?这里运用到了Java的基础知识,我们在更新数据前和更新数据后打印mList的内存地址(System.identityHashCode(mList))值来验证一下:

/com.xxx.test E/tag: 250846535  
/com.xxx.test E/tag: 59754868

发现前后打印的两个值并不相同,证明不是一个对象。这就是导致调用AdapternotifyDataSetChanged()方法不起作用的根本原因。

补充:

1、Java中是没有直接获取内存地址的方法,上面的值是通过System.identityHashCode(mList)得来的。这个值是通过对象的内存地址算出来的,所以可以间接的认为是内存地址,所以只要是同一个对象的话,那么System.identityHashCode(object)值是不变的。
2、System.identityHashCode(object)object.hashCode()的区别:前者的话由于是根据内存地址算出来的,所以是唯一的,只要这个值相等,就可以认为是同一个对象。而后者这个方法是可以重写的,例如String、List都将这个方法重写了,所以可能得到的hashCode相同,但实际却是不同的对象。

解决

既然我们发现使用的不是一个对象,那这就简单了,修改如下:

// 获取到数据进行更新
private void updateData(List<String> list) {
      mList.clear();
      mList.addAll(list);
      mAdapter.notifyDataSetChanged(); //刷新
}

代码很简单,这样就保证了更新数据前后,mList始终为同一个对象。我们继续通过打印内存地址验证一下:

/com.xxx.test E/tag:  250846535
/com.xxx.test E/tag:  250846535

发现内存地址一致,大功告成~

总结

  • 通过System.identityHashCode(object)方法来间接的获取内存地址;
  • 创建出来的对象,只要没被销毁,内存地址始终不变。
  • Adapter绑定的数据源集合要为同一个集合,notifyDataSetChanged()方法才有效,否则需要重新设置数据源。

欢迎各位大神批评指教,感谢~

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Android 开发,ListView 是常用的列表控件,而 Adapter 则是 ListView 显示列表数据的适配器。当数据源改变时,我们需要调用 AdapternotifyDataSetChanged() 方法来通知 ListView 更新数据。不过有时候,我们会发现调用 notifyDataSetChanged() 方法后,ListView 并没有更新数据,这通常是由以下几个原因造成的: 1. 数据源没有更新 在调用 notifyDataSetChanged() 方法之前,需要先确保数据源已经更新了。如果数据源没有更新,调用 notifyDataSetChanged() 方法也不会更新 ListView 显示的数据。 2. Adapter 对象没有重新设置 如果使用的是同一个 Adapter 对象,那么需要重新设置 Adapter 对象才能更新 ListView 显示的数据。可以通过 setAdapter() 方法重新设置 Adapter 对象。 3. ListView 没有重新绘制 当调用 notifyDataSetChanged() 方法后,ListView 并不会立即重新绘制,而是等到系统认为需要重新绘制时才会更新。可以通过调用 invalidate() 方法让 ListView 立即重新绘制。 4. 数据源和 Adapter 对象不匹配 如果数据源和 Adapter 对象不匹配,即数据源的数据类型和 Adapter 的数据类型不一致,调用 notifyDataSetChanged() 方法也无法更新 ListView 显示的数据。 综上所述,如果在 ListView 调用 notifyDataSetChanged() 方法无效,可以先检查数据源是否更新,是否重新设置 Adapter 对象,是否调用了 invalidate() 方法以及数据源和 Adapter 对象是否匹配。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值