RecyclerView遇到的两个bug

90 阅读2分钟

使用增删item时,为了动画效果,不能使用notifyDataSetChanged,而是采用 notifyItemInserted(position);和 notifyItemRemoved(position);如果用形参里的position,导致变化后的条目在UI的位置与其本身索引不对应的问题


//使用getLayoutPosition,而不是形参里的position

 int pos = holder.getLayoutPosition();


package com.anew.recyclerviewall;



import android.content.Context;

import android.support.v7.widget.RecyclerView;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.LinearLayout;

import android.widget.TextView;

import android.widget.Toast;



import java.util.List;

import java.util.Random;



/**

 * Created by a on 2017/1/7.

 */

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VH> {

    private Context context;

    private List<String> list;



    public MyAdapter(Context context, List<String> list) {

        this.context = context;

        this.list = list;

    }



    @Override

    public VH onCreateViewHolder(ViewGroup parent, int viewType) {

//        ★建议用这种方法加载布局,否则会出现match_parent、margin无效的情况,还得保证recyclerView宽高不是wrap_content

        LayoutInflater inflater = LayoutInflater.from(context);

        View view = inflater.inflate(R.layout.item_body, parent, false);

//         采用以下方式,会match_parent无效

//        View view = View.inflate(context, R.layout.item_body, null);

        return new VH(view);

    }



    @Override

    public void onBindViewHolder(final VH holder, final int position) {

        holder.mTv.setText(list.get(position));

        ViewGroup.LayoutParams params = holder.mLl.getLayoutParams();



//        setItemRandomHeight(holder, params);



        holder.mTv.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

//                ★一定要是使用holder.getLayoutPosition来获取新的position

//                这能保证你当前点击的item的索引值是正确的

//                不然如果你想使用item的animation效果,又不能使用notifyDataSetChanged更新

//                数据时(使用了他会失去动画效果),而是使用了notifyItemInserted(pos)

//                通知更新数据,之后,你还是用普通的position时,你会发现这个item的索引和

//                其在ui上的位置并不一致,这是必须使用holder.getLayoutPosition()了

                int pos = holder.getLayoutPosition();

                int adapterPosition = holder.getAdapterPosition();

                int layoutPosition = holder.getLayoutPosition();

                int oldPosition = holder.getOldPosition();

                int positionp = holder.getPosition();



//                事实证明adapterPosition=layoutPosition=positionp

//                oldPosition永远等于-1

//                普通的position在没有notifyDataSetChanged之前是原来列表的索引值



//                所以在设置点击事件时(或者你用回调把点击事件写在外面),传入

//                layoutPosition是妥当的,而不是传入形参里带来的position

                Log.e("eee", "adapterPosition: "+adapterPosition);

                Log.e("eee", "layoutPosition: "+layoutPosition);

                Log.e("eee", "oldPosition: "+oldPosition);

                Log.e("eee", "positionp: "+positionp);

                Log.e("eee", "position: "+position);

//                addData(3);

                removeData(pos);

                Toast.makeText(context,adapterPosition+"",Toast.LENGTH_SHORT).show();

            }



        });

    }



//    item高度随机设置

    private void setItemRandomHeight(VH holder, ViewGroup.LayoutParams params) {

        int height = new Random().nextInt(4)*90+90;

        params.height= height;

        holder.mLl.setLayoutParams(params);

    }



    @Override

    public int getItemCount() {

        return list.size();

    }



    public void addData(int position) {

        list.add(position, "Insert One");

//       ★★★★ 使用notifyItemInserted去更新数据,否则没有动画效果

        notifyItemInserted(position);

    }



    public void removeData(int position) {

//        ★★★★

        list.remove(position);

        notifyItemRemoved(position);

        }

    class VH extends RecyclerView.ViewHolder {



        private TextView mTv;

        private LinearLayout mLl;



        public VH(View itemView) {

            super(itemView);

            mTv = (TextView) itemView.findViewById(R.id.tv);

            mLl = (LinearLayout) itemView.findViewById(R.id.ll);

        }

    }

}