美文网首页
RecycleView简单总结

RecycleView简单总结

作者: _Felix__ | 来源:发表于2019-05-01 20:14 被阅读0次

    基础知识

    下拉加载更多

    https://www.jianshu.com/p/b502c5b59998

    基本实现

    RecycleView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
    
    //设置布局管理器  必选
    /*  
    RecyclerView提供了三种布局管理器:
    LinerLayoutManager 以垂直或者水平列表方式展示Item
    GridLayoutManager 以网格方式展示Item
    StaggeredGridLayoutManager 以瀑布流方式展示Item
    
    如果你想用 RecyclerView 来实现自己自定义效果,则应该去继承实现自己的 LayoutManager,
    并重写相应的方法,而不应该想着去改写 RecyclerView。
    */
    LinearLayoutManager layoutManager = new LinearLayoutManager(this);  
    recyclerView.setLayoutManager(layoutManager);  
    
    //设置为垂直布局,这也是默认的  
    layoutManager.setOrientation(OrientationHelper. VERTICAL);  
    
    //设置Adapter  必选
    recyclerView.setAdapter(recycleAdapter);  
    
     //设置分隔线  可选(默认为空)
    recyclerView.addItemDecoration( new DividerGridItemDecoration(this) );  
    //设置增加或删除条目的动画  可选(默认为DefaultItemAnimator)
    recyclerView.setItemAnimator( new DefaultItemAnimator());  
    

    点击事件

    • 可以监听RecyclerView的Touch事件然后判断手势做相应的处理,
    • 也可以通过在绑定ViewHolder的时候设置监听,然后通过Apater回调出去

    Adapter

    // ① 创建Adapter
    public class NormalAdapter extends RecyclerView.Adapter<NormalAdapter.VH>{
        //② 创建ViewHolder
        public static class VH extends RecyclerView.ViewHolder{
            public final TextView title;
            public VH(View v) {
                super(v);
                title = (TextView) v.findViewById(R.id.title);
            }
        }
        
        private List<String> mDatas;
        public NormalAdapter(List<String> data) {
            this.mDatas = data;
        }
    
        public void updateData(ArrayList<String> data){
            this.mData = data;
            notifyDataSetChanged();
        }
    
        //1.定义点击回调接口
        public interface OnItemClickListener{
            void onItemClick(View view, int position);
            void onItemLongClick(View view, int position);
        }
        //2.定义一个设置点击监听器的方法
        public void setOnItemClickListener(MyAdapter.OnItemClickListener listener){
            listener.onItemClickListener = listener;
        }
    
        //③ 在Adapter中实现3个方法
        @Override
        public void onBindViewHolder(VH holder, int position) {
            holder.title.setText(mDatas.get(position));
            /*holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //item 点击事件
                }
            });*/
            //3.对RecycleView的每一个itemView设置点击事件
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View v) {
                    if(onItemClickListener != null) {
                        int pos = holder.getLayoutPosition();
                        onItemClickListener.onItemClick(holder.itemView, pos);
                    }
                }
            });
    
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if(onItemClickListener != null) {
                        int pos = holder.getLayoutPosition();
                        onItemClickListener.onItemLongClick(holder.itemView, pos);
                    }
                    //表示此事件已经消费,不会触发单击事件
                    return true;
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return mDatas.size();
        }
    
        @Override
        public VH onCreateViewHolder(ViewGroup parent, int viewType) {
            //LayoutInflater.from指定写法
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false);
            //不能是inflate(R.layout.item_1,null);
            return new VH(v);
        }
    }
    

    常见的坑

    • 局部刷新闪屏问题解决
      对于RecyclerView的Item Animator,有一个常见的坑就是“闪屏问题”。
      这个问题的描述是:当Item视图中有图片和文字,当更新文字并调用notifyItemChanged()时,文字改变的同时图片会闪一下。这个问题的原因是当调用notifyItemChanged()时,会调用DefaultItemAnimator的animateChangeImpl()执行change动画,该动画会使得Item的透明度从0变为1,从而造成闪屏。解决办法很简单,在rv.setAdapter()之前调用((SimpleItemAnimator)rv.getItemAnimator()).setSupportsChangeAnimations(false)禁用change动画。
    • RecycleView把Toolbar挡住的问题解决
      • 原因分析:RecycleViewToolbar 都是放置在CoordinatorLayout中的,而CoordinatorLayout是一个加强版的FrameLayout
      • 解决方案:AppBarLayout

    补充

    可通过ItemTouchHelper类 轻易实现拖拽,侧滑删除

    ListView 和RecycleView的差异

    刷新

    ListView
    我们都知道ListView通过adapter.notifyDataSetChanged()实现ListView的更新,这种更新方法的缺点是全局更新,即对每个Item View都进行重绘。但事实上很多时候,我们只是更新了其中一个Item的数据,其他Item其实可以不需要重绘。
    这里给出ListView实现局部更新的方法:

    public void updateItemView(ListView listview, int position, Data data){
        int firstPos = listview.getFirstVisiblePosition();
        int lastPos = listview.getLastVisiblePosition();
        if(position >= firstPos && position <= lastPos){  //可见才更新,不可见则在getView()时更新
            //listview.getChildAt(i)获得的是当前可见的第i个item的view
            View view = listview.getChildAt(position - firstPos);
            VH vh = (VH)view.getTag();
            vh.text.setText(data.text);
        }
    }
    

    可以看出,我们通过ListView的getChildAt()来获得需要更新的View,然后通过getTag()获得ViewHolder,从而实现更新。

    RecyclerView
    RecyclerView提供了notifyItemInserted(),notifyItemRemoved(),notifyItemChanged() 等API更新单个或某个范围的Item视图。

    缓存

    基本上相似。ListView和RecyclerView最大的区别在于数据源改变时的缓存的处理逻辑,ListView是”一锅端”,将所有的mActiveViews都移入了二级缓存mScrapViews,而RecyclerView则是更加灵活地对每个View修改标志位,区分是否重新bindView。

    RecyclerView四级缓存:
    mAttachedScrap 缓存在屏幕上的ViewHolder
    mCachedViews 缓存屏幕外的ViewHolder,默认为2个
    mViewCacheExtensions
    mRecyclerPoor

    回收机制

    基本上相似。ListView是以View作为单位进行回收,RecyclerView是以ViewHolder作为单位进行回收。

    参考文献:https://www.jianshu.com/p/4f9591291365

    相关文章

      网友评论

          本文标题:RecycleView简单总结

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