RecyclerView利用LayoutManager查找控件的BUG

最近在做一个小说书架的App,书架列表采用RecycleView展示,用过小说APP的童鞋都知道书架会有一个编辑功能用来添加或者删除小说。

首先先描述下我碰到的现象

这是默认展示状态


这里写图片描述


当我需要编辑的时候点击右上角的编辑按钮
显示Item中的CheckBox

这里写图片描述


这是后我滑动一段距离后 在点击取消隐藏Item中的CheckBox,发现有一些没有被隐藏

这里写图片描述


因为使用的RecycleView,Item的显示由相应的LayoutManger来处理

LinearLayoutManager提供了如下几个方法来帮助开发者获取屏幕上的顶部item和底部item:

findFirstVisibleItemPosition()
findFirstCompletelyVisibleItemPosition()
findLastVisibleItemPosition()
findLastCompletelyVisibleItemPosition()

首先我通过RecyclerView的LayoutManager获取第一个和最后一个View所对应的Position
这里写图片描述

然后通过for循环查找出CheckBox
这里写图片描述

然而mLinearManager.getChildAt(i)在first和last范围中的View竟然会返回null,这让我很郁闷,然后google、百度一顿查找最后通过findViewByPosition()方法找出View 然后通过RecyclerView的
getChildViewHolder获取ViewHolder对象,然后再找出CheckBox

这里写图片描述

满心欢喜的以为这次可以了,运行之后发现确实不出现为null的现象的,但是依然发现比当前firstItem的position小2的在屏幕外的View划出来依然出现没有隐藏或显示的问题(太绕嘴了)
(这里我十分确定adapter的bindView中对于隐藏和显示的处理)

这里写图片描述

最后我觉可能是RecycleView的回收机制并不是像ListView一样预加载一个 而是二个,并未再次调用bindView方法(这里仅仅是猜测,我也没有查看源码,只是记录一下对于这个BUG的猜测

最后只好调用adapter的notifyDataChange 强制刷新UI了,如果大家有遇到这样的BUG,并且有解决办法的,希望能告诉我,十分感谢

//2017年10月13日 补充

之前猜测的竟然猜全对了!确实是预加载两个,也确实没执行bindView方法,兴奋之余前来补充,正好准备一些面试问题的是,查看listView和RecyclerView的对比发现两者的缓存机制是不同的

这里写图片描述

这里写图片描述

ListView和RecyclerView缓存机制基本一致:

1). mActiveViews和mAttachedScrap功能相似,意义在于快速重用屏幕上可见的列表项ItemView,而不需要重新createView和bindView;

2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,目的是让即将进入屏幕的ItemView重用.

3). RecyclerView的优势在于a.mCacheViews的使用,可以做到屏幕外的列表项ItemView进入屏幕内时也无须bindView快速重用;b.mRecyclerPool可以供多个RecyclerView共同使用,在特定场景下,如viewpaper+多个列表页下有优势.客观来说,RecyclerView在特定场景下对ListView的缓存机制做了补强和完善。

(吐槽一下,无须bindView可以快速重用 mmp啊 对于这个问题我并不觉得是优势啊,当然可能我比较low,这不是个坑吗,不执行bindView 那么写的判断隐藏显示根本就不执行啊!这貌似就是原因啊,遵循这个思路是不是就可以找到解决问题的方法啊!)

然而博客中提到的问题依然没有解决 哭~~ 慢慢来吧 最近比较忙 也许在学习的过程中能找到答案,如果大家有解决了的,还希望能告诉我,十分感谢。

猜你喜欢

转载自blog.csdn.net/omyrobin/article/details/51088490