Android RecyclerView中ViewHolder的复用导致数据错乱解决办法

看图:



视觉效果、recyclerview的基本用法都不说了,超级简单,稍后看代码。

重点来说说item状态的保存问题,其实这个也不是什么新鲜问题,处理起来也不难,方法众多,有setTag的,也有保存到map的。接下来我展示一种自认为更优的方式。

先描述问题,如上图,我们选中了第三个item。然后滑动RecyclerView,让第三个item移出界面后,在滑回来,item的状态是否还在?

由于滑动,view的复用,会丢失之前item选中的状态,但是,但是,item上显示的数据为什么没有错乱呢?这是因为数据集合没有错乱。那么我们能不能把item上需要保存的状态,也与数据集合一同保存呢?这样是不是就不会错乱。当然可以,这样更容易理解。

在数据集合中需要预留本地字段来保存状态。

适配器中的部分代码:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VH> {
    //...
    private ArrayList<UserBean> mLists = new ArrayList<>();
    //...
}

故,UserBean中添加字段:

public class UserBean {

    //后台返回的json字段
    public String userName;
    public String userPwd;
    //...


    //本地字段,用户recyclerview保存状态
    public boolean isSelected = false;
}

在适配器中操作的核心部分代码:

/**
 * @DateTime: 2016-07-26 14:31
 * @Author: duke
 * @Deacription:
 */
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VH> {
    //...
    private ArrayList<UserBean> mLists = new ArrayList<>();

    //记录上次的位置和容器
    private LinearLayout oldContainer;
    private int oldPosition;

    @Override
    public void onBindViewHolder(VH holder, final int position) {
        //强制关闭复用
        //holder.setIsRecyclable(false);
        final UserBean user = this.mLists.get(position);
        holder.word.setText(user.userName);
        if (user.isSelected) {
            //选中的样式
            holder.container.setBackgroundResource(R.drawable.item_bg_press);
        } else {
            //未选中的样式
            holder.container.setBackgroundResource(R.drawable.item_bg);
        }
        holder.container.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null)
                    listener.onDKClick(view, mLists.get(position), position);
                //复原old位置
                if (oldContainer != null) {
                    oldContainer.setBackgroundResource(R.drawable.item_bg);
                    if (oldPosition >= 0 && oldPosition < MyAdapter.this.mLists.size())
                        MyAdapter.this.mLists.get(oldPosition).isSelected = false;
                }
                //设置新的位置样式
                oldContainer = (LinearLayout) view;
                oldPosition = position;

                oldContainer.setBackgroundResource(R.drawable.item_bg_press);
                MyAdapter.this.mLists.get(oldPosition).isSelected = true;
            }
        });
    }

    //...
}

1、当对当前item做点击等事件操作时,需要把当前状态值保存到对应集合的对象中去。

2、复位上一个被点击的item状态。

3、当再次展示该item赋值时,根据集合中对应对象的数据来初始化item状态。


就是这么简单,直观易懂。listview、gridview等雷同的问题都可以这么解决。


http://download.csdn.net/detail/fesdgasdgasdg/9883490

  • 15
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 40
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值