在使用RecyclerView中遇到notifyDataSetChanged列表不刷新问题,表现是:列表滑动时,notifyDataSetChanged可以正常刷新界面,但Fragment切换Tab后,再次滑动RecycleView,列表不刷新。
通过打断点调试,发现数据请求没有问题,每次滑动到底部时自动请求数据,在数据集上添加网络数据,通过打断点信息可得到size由20变为40,数据没有问题:notifydatasetchanged不刷新
先看下notifyDataSetChanged实现:
public final void notifyDataSetChanged() {
mObservable。notifyChanged();
}
比较明显,观察者模式实现,数据改变了,通知观察者刷新。如果不刷新了,有几个怀疑点:
1:数据地址变了,不是同一个对象
打个比方:在数据A上注册了观察者,后面我们更改了数据B,然后调用了notify,此时必然列表不更新,常见的问题及解决办法:
list = data;
notifyDataSetChanged;
改为
list。clear();
list。addAll(data);
notifyDataSetChanged;
2:recycleview地址变了,不是同一个对象
情况类似1,只是由数据换成了recycleview,观察者不是同一个了,此时notify,更新的不是当前recycleView实例,因此必然看不到界面刷新。
此问题需要结合业务去看,主要通过打断点去看,notifyDataSetChanged时是否是同一个对象notifydatasetchanged不刷新
3:数据和recycleview都是同一个地址,但绑定关系不在了
打个比方,数据A上注册了recycleview R,然后经过其他操作(如切换ntab),在切换tab声明周期中,无意间调用了unregisterAdapterDataObserver,导致A和R的绑定关系不在了,因此R不再刷新,
本次遇到的问题正好是情况3,单步调试下看下结果:
recyclerView和dataSource地址都没变(主要看@后面的数字),然后再notifyDataSetChanged处加断点,看内部执行情况,发现:
观察者的List为空了,按照猜测,肯定是无意间调用了unregisterAdapterDataObserver,导致数据和RecycleView绑定关系不在了,因此在unregisterAdapterDataObserver处打断点:
发现在封装时,在onDetachedFromWindow中无意间调用了unregisterAdapterDataObserver,问题根源已找到,解决办法:
unregisterAdapterDataObserver调用可以用标志位来控制,业务在使用封装的recycleview时,复写此标志位,用来控制是否unregister,这个地方需小心Recycleview的泄漏问题。
学过Android开发的人都知道,ListView控件在开发中经常遇到,并且ListView通常结合Adapter适配器来进行数据显示和数据更新操作。姑且假设数据存储在名为dataList的成员变量中。数据操作无非是增加数据、删除数据这两种主要的操作,而当数据有所变化时,为了及时向用户提供更新后的数据,我们知道需要在数据更新后调用适配器的notifyDataSetChanged()方法,来显示更新后的数据。殊不知,该方法并非百试不爽,在此我们便来讨论下具体的原因,其实本质是关注内存的分配情况。
先来看几段代码。
代码段1(某Activity中):
private List<Map<String,String>> dataList;
private ListView listView;
private ListAdapter adapter;
listView = findViewById(R。id。mancard);
adapter = new ListAdapter(this, dataList);
listView。setAdapter(adapter);
上述代码是把Adapter适配器和ListView控件进行绑定。
代码段2(ListAdapter中的部分代码):
public class ListAdapter extends BaseAdapter{