赞
踩
上周,之前的一个朋友发消息给我,RecyclerView的notifyDataSetChanged()方法没有用。心里一想,自己之前不就是这么用的么。但是好像脑海里有看到过也有人遇到了类似的问题,所以还是把迷雾拨开吧。
自己一直有一个习惯,遇到问题不会先谷歌,会先点到源码里面看一下,再查官方文档,再谷歌。点进notifyDataSetChanged源码里面看了一下,就一行代码,但是能看到很多的东西。
一行代码,看出了一个设计模式,观察者模式,从这里就可以猜到通过数据的改变,让观察者来改变数据。但是这里并不能看出为什么这个方法有的人会调用失效。查阅官方文档。
文档写的很清楚,这个方法就是刷新数据的。图中用红框框标记出来的。当前有两种方式可以使数据刷新,第一种是item的数据改变了,但是结构没改变(也就是item的位置没改变),第二种是发生了item的插入,删除等操作的时候。看完这里,这个方法不就是刷新数据的吗?但是怎么会有不起作用的现象呢?还是返回源码里面找吧。
既然notifyDataSetChanged()这个方法中就一行代码,并没有很多的信息,就往上看一层。setAdapter()
这个方法主要起作用的其实是中间的那个方法。setAdapterInternal(adapter, false, true);继续往下看
代码中主要就是个adapter添加一个观察者,那么这个观察者也就是重点。看一下这个mObserver
在调用notifyDataSetChanged()完成后就会调用观察者对象的onChange()方法来刷新数据。流程就是这样,感觉设计的很巧妙,但是为啥就没效果了呢?然后让朋友把代码发给了我。
大体一看,并没有看到什么错误。但是代码中真的存在错误,观察到这两行代码了吗?
其实就是这里出现了问题。刚开始list是个空的对象,然后把空的集合数据塞给了adapter,于是有了他的一个观察者RecyclerViewDataObserver,他观察的是这个list对象所指的地址上的堆内存里的数据。但是现在通过网络访问拿到数据以后,直接用list指向了data,现在list指向的地址变了,数据也有了。但是RecyclerViewDataObserver观察的永远是list刚开始所指的那个地址。所以不会起作用。为了好理解,画个图:
oberserber永远观察的都是地址0x0001上的数据。现在list是有值了,但是地址变了。调用notifyDataSetChanged当前没有用了。
使用这种方式可以解决上面的问题,现在就把数据加到0x0001这个地址里了,调用刷新方法,搞定。
虽然是一个小问题,但是能反应出很多问题, 一个小问题很可能会花大量的时间找答案。总结问题,成就将来。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。