背景:
有A和B两个Adapter,先给RecyclerView设置A,某种情况下再给RecyclerView设置B,A和B的item布局相似度非常的高,现在的问题是我再互相切换adapter的时候会出现界面混乱,上面title的变化说明adapter已经切换了:
分析:
最开始直接用的setAdapter(A?B)来切换,不行.查看方法,发现还有 mRecycler.removeAllViews()方法,在切换adapter的时候,先执行removeAllViews(),还是不行!继续看源码,发现有个方法,
swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews)
看到这个方法我虎躯一震,来了个swapAdapter(A?B,true),想着这下应该可以了吧,然而并没有什么卵用!还是有脏界面,仔细看了下参数removeAndRecycleExistingViews,原来他意思是:当参数2设置为true时,它的效果和setAdapter()一样,旧的item会被回收重新用,设置为false,那么全部的item都会被重新创建。
我虎躯又是一震,改代码为swapAdapter(A?B,false),运行一看,还是界面和数据都脏乱.以前我也用过切换adapter,屁事没有,今天这bug已经超出我的想象和控制范围了,有点凌乱了,背后也开始冒汗了......
RecyclerView的Adapter我用的是阿里的VLayou和封装后的DelegetAdapter,我在想是不是VLayout的锅,把DelegetAdapter替换成最原生的RecyclerView.Adapter,运行还是没什么卵用。
能力不行得求助大神了,我微信了VLayout的原生开发这灰风大哥,大哥说
布局不对就是Layouthelper不正确 让我朝这个思路看看为什么没有设置新的layouthelper到virtuallayoutmanager。两个Adapter的LayoutManager都是用的LinearLayoutManager,所以基本排除这个假设。
大哥建议我从新创建视图,比如再放一个Recyc,通过控制显示和隐藏来达到切换的目的.这虽是一种解决方法,但不是程序员所为!
然后我又想到是不是checkBox,毕竟CheckBox遇上Rcyc本身就是一种Bug,但是从上图可以看出,不仅脏界面也脏数据,那说明不是CheckBox的锅,排除。
这个小b功能因为这个Bug严重的耽误了我的进度,然而我完全是束手无策,我特么都悄悄求着UI小姐姐能不能把这恶心设计更改了。小姐姐仅仅用一个眼神杀死了我!
我颓废的一边想着其他方式实现这个设计,一边想着放弃这种方式,也一边想着为什么会这样?这个功能其实就是仿的钉钉的联系人组织架构,我想起之前用DDMS看过它是用ListView实现的(当时是想看他的横向指示器是用的什么控件实现的)。ListView,RecyclerView我突然又想到了什么!!!
之前看面试题的时候,看到过Listview是二级缓存,缓存的view,而RecyclerView做的是四级缓存,缓存的是holde。
缓存!!!
我大概已经知道是什么原因了,翻开初始化RecyclerView的代码,看见有四行代码:
我默默将这四行代码删除,运行,完美!!!!
这四句代码是给RecyclerView设置缓存池,至于作用看图片中的注释就明白了。
解决办法:
别给RecyclerView设置缓冲池。
结语:
讲道理,无论我何种方式切换,无论我item的布局是不是类似,无论是否设置了缓存池,我特么在切换的时候就不应该出现脏数据。谷歌大厂的Bug
网友评论