【安卓学习之常见问题】 RecyclerView刷新之后Item位置改变

█ 【安卓学习之常见问题】 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

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值