美文网首页APP开发经验总结
RecyclerView正确使用notify(notifyIte

RecyclerView正确使用notify(notifyIte

作者: 不识水的鱼 | 来源:发表于2019-07-28 00:43 被阅读0次

    一款Android App能不能告诉我你不使用RecyclerView(这个好像可以有),这个应该很少了吧。那么数据刷新是不是还是一个notifyDataSetChanged()一刷到底呢 ?在适配器的刷新方法里,其实还有这么几个常用的 notify

    1. 刷新全部的item,notifyDataSetChanged()   
    2. 刷新指定的item,notifyItemChanged(int)   
    3. 从指定的位置开始刷新指定个item,notifyItemRangeChanged(int,int) 这个刷新onBindViewHolder方法,position才能保持一直
    4. 插入、移动指定位置的item,并刷新,notifyItemInserted(int)、notifyItemMoved(int)、notifyItemRemoved(int)  (有坑记得要填)
    5. 局部刷新指定的数据,notifyItemChanged(int, Object)
    

    正题:demo测试几个刷新,且填坑。
    界面图长这样

    Screenrecord-2019-07-27-23-38-08-547_20190727235031

    简单实现的adapter

    /**
     * author: kun .
     * date:   On 2019/7/25
     */
    public class RVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<Data> mDataList;
    private Context mContext;
    
    public RVAdapter(List<Data> dataList, Context context) {
        mDataList = dataList;
        mContext = context;
    }
    
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view= LayoutInflater.from(mContext).inflate(R.layout.rv_item_layout,null);
        return new RVHolder(view);
    }
    
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, final int position) {
        if(viewHolder instanceof RVHolder){
            final Data data = mDataList.get(position);
            ((RVHolder) viewHolder).mTvName.setText(data.getName());
            ((RVHolder) viewHolder).mTvDes.setText(data.getDes());
            Glide.with(mContext).load(data.image).placeholder(R.mipmap.ic_launcher).into(((RVHolder) viewHolder).mImageView);
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, "name:"+data.getName()+" pos:"+position, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    
    @Override
    public int getItemCount() {
        return mDataList.size();
    }
    
    class RVHolder extends RecyclerView.ViewHolder{
        ImageView mImageView;
        TextView mTvName,mTvDes;
        public RVHolder(@NonNull View itemView) {
            super(itemView);
            mImageView=itemView.findViewById(R.id.iv_image);
            mTvName=itemView.findViewById(R.id.tv_name);
            mTvDes=itemView.findViewById(R.id.tv_des);
        }
    }
    }
    

    测试用例,简单布局
    Activity里的调用如下:
    1.一键傻瓜式刷新

    Screenrecord-2019-07-27-23-38-08-547_20190727235031
     mDataList.addAll(addData());
     mRvAdapter.notifyDataSetChanged();
    

    notifyDataSetChanged()一键刷新,解决80%的刷新问题,刷新走一波

    2.一键移除花式刷新

    Screenrecord-2019-07-27-23-38-08-547_20190727235031.gif
        mRvAdapter.notifyItemRemoved(1);
        mDataList.remove(1);
        //受影响的item都刷新position
        mRvAdapter.notifyItemRangeChanged(1, mDataList.size() - 1);
    

    notifyItemRemoved(int)指定移除某个item,mDataList数据一定要同步更新,否者RecyclerView会报错,(坑记得要填)notifyItemRangeChanged(1, mDataList.size() - 1)记得调用(不信可以试试不调用的后果),否者在点击的时候position仍然是移除之前的position,notifyItemRangeChanged会刷新notifyItemRangeChanged方法,保证position的准确位置,刷新后的position与数据相匹配。notifyItemRemoved(int)自带刷新动画,花式移除item.
    3.一键插入花式刷新

    Screenrecord-2019-07-27-23-38-08-547_20190727235249.gif
    Data data=new Data();
    data.setName("name:"+"插入");
    data.setDes("des:"+"插入");
    data.setImage(refreshImage);
    mDataList.add(1,data);
    mRvAdapter.notifyItemInserted(1);  
    mRvAdapter.notifyItemRangeChanged(1, mDataList.size() + 1);
    

    notifyItemInserted(int)花式插入数据,与一键移除花式刷新差不多,同时notifyItemRangeChanged(1, mDataList.size() + 1)千万别忘了,否者会有多个item同一个position(后果很严重的哦)。
    4.一键移花接木式刷新

    Screenrecord-2019-07-27-23-38-08-547_20190727235516.gif
         //注意位置的变换 1 和 4 交换
         Data remove4 = mDataList.remove(4);
         Data remove1 = mDataList.remove(1);
         mDataList.add(1,remove4);
         mDataList.add(4,remove1);
         mRvAdapter.notifyItemMoved(4,1);
         //受影响的item都刷新position
          mRvAdapter.notifyItemRangeChanged(Math.min(4, 1), Math.abs(4 - 1) +1);//受影响的item都刷新position
    

    notifyItemMoved(int fromPosition, int toPosition)带动画的移动item,从指定位置到指定位置的移动,数据更新加移动动画,同样notifyItemRangeChanged(Math.min(4, 1), Math.abs(4 - 1) +1)同样的作用,忘记调用会吃大亏。

    5.一键指定刷新

    Screenrecord-2019-07-27-23-38-08-547_20190727235707.gif
                Data data1=new Data();
                data1.setImage(refreshImage);
                mDataList.get(1).setImage(refreshImage);
                mRvAdapter.notifyItemChanged(1,data1);
    

    Screenrecord-2019-07-27-23-38-08-547_20190727235758.gif
                mDataList.get(1).setImage(refreshImage);
                mRvAdapter.notifyItemChanged(1);
    

    局部刷新notifyItemChanged(int position),notifyItemChanged(int position,Object payload),两个方法都是局部刷新的方法,RecyclerView特色刷新方式,指定位置进行刷新,比如item有进度条数据,这种数据变化频繁,或者聊天界面都会使用局部刷新。

    6.自定义局部刷新

    Screenrecord-2019-07-27-23-38-08-547_20190728000202.gif
    //获取到viewholder的view
        View viewHolder = mGridLayoutManager.findViewByPosition(3);
        mDataList.get(3).setImage(notifyImage);
        ImageView imageView=viewHolder.findViewById(R.id.iv_image);
        Glide.with(this).load(notifyImage).placeholder(R.mipmap.ic_launcher).into(imageView);
    

    通过mGridLayoutManager.findViewByPosition(3)布局管理器,可以获取到指定的item,获取到指定的View,就可以实现对这个View的操作。实现刷新

    Activity的完整代码

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
    private RecyclerView mRvList;
    private List<Data> mDataList=new ArrayList<>();
    private String image="http://ww3.sinaimg.cn/large/610dc034gw1f9shm1cajkj20u00jy408.jpg";
    private String refreshImage="http://ww3.sinaimg.cn/large/610dc034jw1fa2vh33em9j20u00zmabz.jpg";
    private String notifyImage="http://ww2.sinaimg.cn/large/610dc034jw1f9vyl2fqi0j20u011habc.jpg";
    private Button mBtNotify_1;
    private Button mBtNotify_2;
    private Button mBtNotify_3;
    private Button mBtNotify_4;
    private Button mBtNotify_5;
    private Button mBtNotify_6;
    private Button mBtNotify_7;
    private RVAdapter mRvAdapter;
    private GridLayoutManager mGridLayoutManager;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initListener();
    }
    
    private void initView() {
        mRvList = findViewById(R.id.recyclerview);
        mBtNotify_1 = findViewById(R.id.bt_notify_1);
        mBtNotify_2 = findViewById(R.id.bt_notify_2);
        mBtNotify_3 = findViewById(R.id.bt_notify_3);
        mBtNotify_4 = findViewById(R.id.bt_notify_4);
        mBtNotify_5 = findViewById(R.id.bt_notify_5);
        mBtNotify_6 = findViewById(R.id.bt_notify_6);
        mBtNotify_7 = findViewById(R.id.bt_notify_7);
        mGridLayoutManager = new GridLayoutManager(this,2);
        mRvList.setLayoutManager(mGridLayoutManager);
        mRvAdapter = new RVAdapter(mDataList,this);
        mRvList.setAdapter(mRvAdapter);
        initData();
        mRvAdapter.notifyDataSetChanged();
    }
    
    private void initData() {
        for (int i = 0; i < 10; i++) {
            Data data=new Data();
            data.setName("name:"+i);
            data.setDes("desc:"+i);
            data.setImage(image);
            mDataList.add(data);
        }
    }
    
    private void initListener() {
        mBtNotify_1.setOnClickListener(this);
        mBtNotify_2.setOnClickListener(this);
        mBtNotify_3.setOnClickListener(this);
        mBtNotify_4.setOnClickListener(this);
        mBtNotify_5.setOnClickListener(this);
        mBtNotify_6.setOnClickListener(this);
        mBtNotify_7.setOnClickListener(this);
        mRvList.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }
    
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int firstVisibleItemPosition = mGridLayoutManager.findFirstCompletelyVisibleItemPosition();
                int lastVisibleItemPosition = mGridLayoutManager.findLastCompletelyVisibleItemPosition();
                for (int i = firstVisibleItemPosition; i <lastVisibleItemPosition; i++) {
                    View view = mGridLayoutManager.findViewByPosition(i);
                    ImageView imageView=view.findViewById(R.id.iv_image);
                    //可实现可见item的动画,而不是绘制item的动画,滑动就会触发动画
    //              setAnimation(imageView);
                }
            }
        });
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_notify_1:
                mDataList.addAll(addData());
                mRvAdapter.notifyDataSetChanged();
                break;
            case R.id.bt_notify_2:
                mDataList.remove(1);
                mRvAdapter.notifyItemRemoved(1);
                //受影响的item都刷新position
                mRvAdapter.notifyItemRangeChanged(1, mDataList.size() - 1);
                //批量删除
                //mRvAdapter.notifyItemRangeRemoved(int positionStart, int itemCount)
                break;
            case R.id.bt_notify_3:
                Data data=new Data();
                data.setName("name:"+"插入");
                data.setDes("des:"+"插入");
                data.setImage(refreshImage);
                mDataList.add(1,data);
                mRvAdapter.notifyItemInserted(1);
                mRvAdapter.notifyItemRangeChanged(1, mDataList.size() + 1);
                break;
            case R.id.bt_notify_4:
                //注意位置的变换 1 和 4 交换
                Data remove4 = mDataList.remove(4);
                Data remove1 = mDataList.remove(1);
                mDataList.add(1,remove4);
                mDataList.add(4,remove1);
                mRvAdapter.notifyItemMoved(4,1);
                //受影响的item都刷新position
                mRvAdapter.notifyItemRangeChanged(Math.min(4, 1), Math.abs(4 - 1) +1);//受影响的item都刷新position
                break;
            case R.id.bt_notify_5:
                Data data1=new Data();
                data1.setImage(refreshImage);
                mDataList.get(1).setImage(refreshImage);
                mRvAdapter.notifyItemChanged(1,data1);
                break;
            case R.id.bt_notify_6:
                mDataList.get(1).setImage(refreshImage);
                mRvAdapter.notifyItemChanged(1);
                break;
            case R.id.bt_notify_7:
                //获取到viewholder的view
                View viewHolder = mGridLayoutManager.findViewByPosition(3);
                mDataList.get(3).setImage(notifyImage);
                ImageView imageView=viewHolder.findViewById(R.id.iv_image);
                Glide.with(this).load(notifyImage).placeholder(R.mipmap.ic_launcher).into(imageView);
                break;
        }
    }
    
    private List<Data> addData(){
        List<Data> datalist=new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            Data data=new Data();
            data.setName("name:"+"refresh-"+i);
            data.setDes("des:"+"refresh-"+i);
            data.setImage(notifyImage);
            datalist.add(data);
        }
        return datalist;
    }
    
    public void setAnimation(View view) {
        ObjectAnimator mObjectAnimator = ObjectAnimator.ofFloat(view, "rotation", -6, 6,6,-6,0);
        mObjectAnimator.setDuration(500);
        mObjectAnimator.setRepeatCount(1);
        mObjectAnimator.setInterpolator(new AccelerateInterpolator());
        mObjectAnimator.start();
    }
    }
    

    相关文章

      网友评论

        本文标题:RecyclerView正确使用notify(notifyIte

        本文链接:https://www.haomeiwen.com/subject/pjhdrctx.html