RecyclerView使用,优化,条目闪烁问题

RecyclerView的基本介绍

RecyclerView是谷歌V7包下新增的控件,用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓.

RecyclerView好处

①RecylerView封装了viewholder的回收复用,也就是说RecylerView标准化了ViewHolder,编写Adapter面向的是 ViewHolder而不再是View了,复用的 逻辑被封装了,写起来更加简单。

②提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecylerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。例如recyclerview不局限与下拉列表,它还支持GridView效果和瀑布流效果

③可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecylerView有其自己默认的实现。

涉及到的类

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。
LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。

RecyclerView的三种显示方式

目前SDK中提供了三种自带的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager

RecyclerView依赖,布局,属性使用

1、添加依赖

implementation ‘com.android.support:recyclerview-v7:27.1.1’

2.然后是在XML文件用使用它

<android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
   />

3.创建完布局之后在MainActivity中获取这个RecyclerView,并声明LayoutManager与Adapter,代码如下:

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
LinearLayoutManager layoutManager = new LinearLayoutManager(this );  
//设置布局管理器  
recyclerView.setLayoutManager(layoutManager);  
//设置为垂直布局,这也是默认的  
layoutManager.setOrientation(OrientationHelper. VERTICAL);  
//设置Adapter  
recyclerView.setAdapter( recycleAdapter);  
 //设置分隔线  
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));  
//设置增加或删除条目的动画  
recyclerView.setItemAnimator( new DefaultItemAnimator());  

RecyclerView的适配器RecyclerView.Adapter

RecyclerView.Adapter

①onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

②onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。

③getItemCount()
这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。

创建适配器和ViewHolder


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

    private final ArrayList<String> mData;
    private final Context mContext;
    private final LayoutInflater mInflater;
    private OnItemClickListener mListener;
    
    public MyAdapter(Context context,ArrayList<String> data) {
        this.mContext = context;
        this.mData = data;
        mInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //创建一个自定义ViewHolder
        View inflate = mInflater.inflate(R.layout.item, parent,false);
        ViewHolder viewHolder = new ViewHolder(inflate);
        return viewHolder;

    }
    
    @Override
    public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, final int position) {
        //将数据与界面绑定
        holder.mTv.setText(mData.get(position));
        if (position%2 == 0){
            holder.mIv.setImageResource(R.drawable.friend_circle_default);
        }else{
            holder.mIv.setImageResource(R.drawable.cate);
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //这个方法被调用的时候,想要让MainActivity知道
                if (mListener != null){
                    mListener.onItemClick(v,position);
                }
            }
        });
    }

    //1.定义一个接口
    public interface OnItemClickListener{
        void onItemClick(View view,int position);
    }

    //2.传递接口类实现对象
    public void setOnItemClickListener(OnItemClickListener listener){
        this.mListener = listener;
    }
    
    @Override
    public int getItemCount() {
        //获取item数量
        return mData.size();
    }
    
    /**
     * RecyclerView 内部封装了VIewHolder的回收复用,标准化了ViewHolder,编写Adapter就是面向ViewHolder,而不是View
     */
    public class ViewHolder extends RecyclerView.ViewHolder{
        private TextView mTv;
        private ImageView mIv;
        public ViewHolder(View itemView) {
            super(itemView);
            mTv = itemView.findViewById(R.id.tv);
            mIv = itemView.findViewById(R.id.iv);
        }
    }
}

RecyclerView接口回调
1.定义接口
在哪里定义?
定义外部接口和内部接口都可以,google一般定义内部,所以我们也定义内部接口
接口里有什么方法
取决于我们要做什么,需要什么方法就定义什么

 //Adapter内部定义
    public interface OnItemClickListener{
        void onItemClick(View view,int position);
    }

2.设置传递接口类实现对象的方法

 public void setOnItemClickListener(OnItemClickListener listener){
        this.mListener = listener;
    }

3.传递接口实现类对象


mAdapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(View view, int position) {
            Toast.makeText(MainActivity.this, "position:" + position, Toast.LENGTH_SHORT).show();
            startActivity(new Intent(MainActivity.this, MultiTypeActivity.class));
        }
    });

Recycleview优化:

1,如果确定recycleview中数据变化的位置,可以对其进行局部刷新

2,在编写布局的时候,如果能通过代码实现排布,可以将xml方式进行替换,提升页面加载的效率;另外尤其在多布局展示中,对应不同item中公用的一些控件或组件,可以通过自定义view的方式,减少view的构造和嵌套。

3,如果一个item中,多个子view都需要设置点击事件的监听,我们可以设置一个全局的监听,然后通过view.getId或view.getTag来找到具体item,将具体view的点击事件设置到viewHolder中,避免列表在不停滑动过程中,犹豫onbindviewholder要反复绘制数据带来的点击事件的重复创建。

4,如果一个recyclerview中嵌套了多个recyclerview,而嵌套recycerview的适配器是一样的,可以共享一个对象池。

5,对recyclerview数据的预加载,当我们加载完一页数据后,不管用户有没有及时上拉查看,我们可以再后台动态的加载一定数量的数据,当列表上划时,计算划出的条目数量,然后从预加载的数据中取出对应条目的数量追加到recycleview末尾,这样给用户更为流畅的滑动体验。

6,对于scrollview中嵌套recyclerview,我们可以调用setNestedScrollingEnabled(false)来禁止recycleview的滑动,以确保外部view可流畅的滑动。

7,如果item高度固定,可以设置RecyclerView.setHasFixedSize(true); 来避免 requestLayout 浪费资源;

8,调用RecyclerView.onViewRecycled(holder) 来回收资源。

9,通过 RecycleView.setItemViewCacheSize(size); 来加大 RecyclerView 的缓存,用空间换时间来提高滚动的流畅性

10,瀑布流上拉加载时发生item抖动,建议采用notifyItemRangeChanged进行局部刷新

关于recycleview刷新是条目闪烁问题

1,如果仅仅是刷新某一个item,一定要调用指定位置的局部刷新,尽量避免更为消耗资源的全部刷新

2,如果没有给item加出场动画,尽量把默认的动画禁止掉,防止onbindviewholder重绘item的时候,由于出场动画给item的刷新带来闪烁的bug

3,对于item中图片的闪烁,一方面要注意图片的加载是否加了出场动画(比如glide默认有出场动画,应该把它禁止掉),第二就是看有没有在刷新的时候动态绘制imageview的形状,如果绘制效率不高的情况下,也会引发图片闪烁,第三在item中尽量不要使用办透明效果,尤其是数据量较大或者涉及到需要频繁刷新的情况,因为半透明绘制底层涉及到大量的数学运算,而这些严重影响item的绘制,所以当item数量庞大时,会出现item闪烁甚至滑动卡顿的问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值