█ 【安卓学习之常见问题】 RecyclerView刷新之后Item位置改变
█ 相关文章:
-
█ 读前说明:
-
● 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
● 本文只简单罗列相关的代码实现过程
● 涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已
█ 我的问题:
-
● 初始化,设置了了6个ItemView缓存,点击item后,调用notifyDataSetChanged()刷新,发现Item位置发生变化。(为了方便测试,刷新界面的时候,item的文字不变,不过图片还是重新刷新了)
可以发现刷新后,ViewHolder中的TextView、EditText都跟着Item位置变化而移动
RecyclerView.RecycledViewPool pool = recyclerView.getRecycledViewPool();
pool.setMaxRecycledViews(0, 6);
recyclerView.setRecycledViewPool(pool);
● 以前为什么没有发现?
1.这里recyclerView采用了GridLayoutManager 布局,每行3个,如果数据只有一行,即少于4个时,是不会出现Item位置发生变化
GridLayoutManager manager = new GridLayoutManager(mContext, 3);
manager.setOrientation(GridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
2.调用notifyDataSetChanged()时,会调用onCreateViewHolder()方法,只需要在这里面,将所有的数据重新更新下,不管位置有没有发现变化,至少界面上显示都是对的,都是按顺序的即可。
注意: RecyclerView内部默认只缓存5个Item,如果调用notifyDataSetChanged()方法刷新列表的,刷新后的列表数据小于5的话,不会重调用onCreateViewHolder()方法,但是如果大于5的话会重新调用onCreateViewHolder创建ItemView,因为RecyclerView内部只缓存了5个ItemView,所以RecyclerView提供了好多局部刷新的方法
█ 定位问题:
● 测试1:
● 测试2:
● 发现:
当刷新的时候,按0-1-2-3-4-5-6 刷新时,item位置会和上次一样;当按3-4-5-2-1-4刷新时,item位置就会发生变化
不管按照什么顺序刷新,onBindViewHolder(ViewHolder holder, int position)中取出来的holder都是按上次的0-1-2-3-4-5-6 取出来,然后显示出来的新位置是position,所以position不是按顺序刷新,那么位置就会发生移位。
可以看出是刷新的顺序导致显示的位置错乱
█ 解决问题:
● 方法一:将recyclerview以及父布局的宽高都修改为match_parent
测试结果:没用
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="30dp"
android:layout_marginTop="14dp"
android:layout_marginRight="30dp" />
</LinearLayout>
● 方法二:将notifyDataSetChanged()修改为局部刷新?
测试结果:没用
for (int i = 0; i < getItemCount(); i++) {
notifyItemChanged(i);
}
notifyItemRangeChanged(0, getItemCount());
● 方法三:网上最多的方法,就是每次刷新,不管是哪个item,都重新刷新,需要View上面缓存的数据,也可以新建一个集合,用来保存所有Item的View上数据(这里主要是指上次输入在EditText中的值),至于其他的图标啊,TextView啊等等,正常都是保存在数据源之中,在里面取出来重新赋值下即可。这种是最方便的方法。
● 方法四:不使用notifyDataSetChanged(),在点击按钮的时候,手动刷新界面:
比如,直接使用for循环进行循环更新Item,写的可能麻烦点,但实际上效率应该比较高。位置也不会变化;
又比如,记录上次点击的item,手动刷新当前的item和上次的item。
● 方法五:可以研究下notifyDataSetChanged()实现原理,看看为什么每次刷新的时候,不是按照0-1-2-3-4-5顺序来刷新,然后看要怎么修复这个bug。
█ 相关资料:
● 1.2018-02-06 Android 解决RecyclerView瀑布流刷新之后Item位置改变_移动开发_wobenxiaozu的博客-CSDN博客
● 2.2018-07-01 Recyclerview 刷新时整体布局跳动的解决办法 - 简书
● 3.2019-10-08 Android-浅谈RecyclerView瀑布流Item位置变换问题_移动开发_Luckly_Du的博客-CSDN博客
● 3.2019-03-10 Android开发RecyclerView使用关于notifyDataSetChanged的坑
转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/106274173