RecyclerView使用介绍

RecyclerView 是Android L版本中新添加的一个用来取代ListView、GridView的SDK,它的灵活性与可替代性比listview更好。接下来通过一系列的文章讲解如何使用RecyclerView,彻底抛弃ListView.了解RecyclerView架构,可以高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator可以实现的想要的效果。

1、首先介绍几种LayoutManager
目前SDK中提供了三种自带的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager

LinearLayoutManager mManager = new LinearLayoutManager(mContent);  
LinearLayoutManager mManager = new LinearLayoutManager(mContent, LinearLayoutManager.VERTICAL, false);//垂直布局,true表示左右翻转数据从后往前显示,false不翻转  数据从0往后显示。
GridLayoutManager mManager = new GridLayoutManager(mContent,3);  
GridLayoutManager mManager = new GridLayoutManager(mContent,3,LinearLayoutManager.HORIZONTAL,false);//每行3列,水平,true表示左右翻转,false不翻转  
mRecyclerView.setLayoutManager(mManager);  
 //设置瀑布流效果
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));

2、RecycleView简单使用

//初始化控件  
mRecyclerView = findView(R.id.id_recyclerview);  
//设置布局管理器  
mManager = new LinearLayoutManager(mContent);  
mRecyclerView.setLayoutManager(mManager);  
//设置adapter  
mRecyclerView.setAdapter(mAdapter)  
//设置Item增加、移除动画  
mRecyclerView.setItemAnimator(new DefaultItemAnimator());  
//添加分割线  
mRecyclerView.addItemDecoration(new DividerItemDecoration(  
                getActivity(), DividerItemDecoration.HORIZONTAL_LIST));  

3、接下来介绍的就是RecyclerView的适配器了,同样,RecyclerView和ListView,GridView一样需要adapter来填充数据,同样,自定义一个adapter需要继承RecyclerView.Adapter,代码需要实现几个父类方法onCreateViewHolder,onBindViewHolder,getItemCount(),根据名字就能知道:
(1)onCreateViewHolder:主要返回的是拿到布局,进而返回ViewHolder
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null));
(2)onBindViewHolder:拿到ViewHolder中的控件对其赋值操作
(3)getItemCount():返回数组的size()
使用前必须先添加依赖包
在AS的build.gradle中添加依赖,然后同步一下就可以引入依赖包:

dependencies {
    compile 'com.android.support:recyclerview-v7:25.3.1'
}

下面是今天主要记录的内容,那就是封装万能的RecyclerView的适配器。
BaseRecyclerAdapter适配器类:

package com.recyclerview;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

/**
 * 作者:willkong on 2017/7/20.
 * QQ号:547860818
 * 作用:万能的RecyclerView适配器
 */

public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerHolder> {

    private Context context;//上下文
    private List<T> list;//数据源
    private LayoutInflater inflater;//布局器
    private int itemLayoutId;//布局id
    private boolean isScrolling;//是否在滚动
    private OnItemClickListener listener;//点击事件监听器
    private OnItemLongClickListener longClickListener;//长按监听器
    private RecyclerView recyclerView;

    //在RecyclerView提供数据的时候调用
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        this.recyclerView = null;
    }

    /**
     * 定义一个点击事件接口回调
     */
    public interface OnItemClickListener {
        void onItemClick(RecyclerView parent, View view, int position);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClick(RecyclerView parent, View view, int position);
    }

    /**
     * 插入一项
     *
     * @param item
     * @param position
     */
    public void insert(T item, int position) {
        list.add(position, item);
        notifyItemInserted(position);
    }

    /**
     * 删除一项
     *
     * @param position 删除位置
     */
    public void delete(int position) {
        list.remove(position);
        notifyItemRemoved(position);
    }

    public BaseRecyclerAdapter(Context context, List<T> list, int itemLayoutId,RecyclerView recyclerView) {
        this.context = context;
        this.list = list;
        this.itemLayoutId = itemLayoutId;
        this.recyclerView = recyclerView;
        inflater = LayoutInflater.from(context);

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                isScrolling = !(newState == RecyclerView.SCROLL_STATE_IDLE);
                if (!isScrolling) {
                    notifyDataSetChanged();
                }
            }
        });
    }

    @Override
    public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(itemLayoutId, parent, false);
        return BaseRecyclerHolder.getRecyclerHolder(context, view);
    }

    @Override
    public void onBindViewHolder(final BaseRecyclerHolder holder, int position) {
        //点击背景
        if (listener != null) {
            holder.itemView.setBackgroundResource(R.drawable.recycler_bg);//设置背景
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null && view != null && recyclerView != null) {
                    int position = recyclerView.getChildAdapterPosition(view);
                    listener.onItemClick(recyclerView, view, position);
                }
            }
        });


        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                if (longClickListener != null && view != null && recyclerView != null) {
                    int position = recyclerView.getChildAdapterPosition(view);
                    longClickListener.onItemLongClick(recyclerView, view, position);
                    return true;
                }
                return false;
            }
        });

        convert(holder, list.get(position), position, isScrolling);

    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

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

    public void setOnItemLongClickListener(OnItemLongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }

    /**
     * 填充RecyclerView适配器的方法,子类需要重写
     *
     * @param holder      ViewHolder
     * @param item        子项
     * @param position    位置
     * @param isScrolling 是否在滑动
     */
    public abstract void convert(BaseRecyclerHolder holder, T item, int position, boolean isScrolling);
}

对应的ViewHolder类BaseRecyclerHolder:

package com.recyclerview;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * 作者:willkong on 2017/7/20.
 * QQ号:547860818
 * 作用:万能的RecyclerView的ViewHolder
 */

public class BaseRecyclerHolder extends RecyclerView.ViewHolder {

    private SparseArray<View> views;
    private Context context;

    private BaseRecyclerHolder(Context context, View itemView) {
        super(itemView);
        this.context = context;
        //指定一个初始为8
        views = new SparseArray<>(8);
    }

    /**
     * 取得一个RecyclerHolder对象
     *
     * @param context  上下文
     * @param itemView 子项
     * @return 返回一个RecyclerHolder对象
     */
    public static BaseRecyclerHolder getRecyclerHolder(Context context, View itemView) {
        return new BaseRecyclerHolder(context, itemView);
    }

    public SparseArray<View> getViews() {
        return this.views;
    }

    /**
     * 通过view的id获取对应的控件,如果没有则加入views中
     *
     * @param viewId 控件的id
     * @return 返回一个控件
     */
    @SuppressWarnings("unchecked")
    public <T extends View> T getView(int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }

    /**
     * 设置字符串
     */
    public BaseRecyclerHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    /**
     * 设置图片
     */
    public BaseRecyclerHolder setImageResource(int viewId, int drawableId) {
        ImageView iv = getView(viewId);
        iv.setImageResource(drawableId);
        return this;
    }

    /**
     * 设置图片
     */
    public BaseRecyclerHolder setImageBitmap(int viewId, Bitmap bitmap) {
        ImageView iv = getView(viewId);
        iv.setImageBitmap(bitmap);
        return this;
    }

//    /**
//     * 设置图片
//     */
//    public BaseRecyclerHolder setImageByUrl(int viewId,String url){
//        Picasso.with(context).load(url).into((ImageView) getView(viewId));
//        //        ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(context));
//        //        ImageLoader.getInstance().displayImage(url, (ImageView) getView(viewId));
//        return this;
//    }
}

分割线类DividerListItemDecoration:

package com.recyclerview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class DividerListItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerListItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
//        Log.e("recyclerview - itemdecoration", "onDraw()");

        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

点击阴影recycler_bg:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
        <shape android:shape="rectangle">
            <solid android:color="#cfd8dc"/>
        </shape>
    </item>
</selector>

使用实例:

package com.recyclerview;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.ArrayList;

import static android.R.attr.data;

public class MainActivity extends Activity implements View.OnClickListener {
    private Button btn_add;
    private Button btn_delete;
    private Button btn_list;
    private Button btn_grid;
    private Button btn_flow;
    private RecyclerView recyclerview;
    private ArrayList<String> datas;
//    private MyRecyclerViewAdapter adapter;
    private BaseRecyclerAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        adapter = new BaseRecyclerAdapter<String>(MainActivity.this, datas, R.layout.item_recyclerview,recyclerview) {
            @Override
            public void convert(BaseRecyclerHolder holder, String item, int position, boolean isScrolling) {
                holder.setText(R.id.tv_title,item);
            }
        };
        recyclerview.setAdapter(adapter);
        recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
        recyclerview.addItemDecoration(new DividerListItemDecoration(MainActivity.this,DividerListItemDecoration.VERTICAL_LIST));
        adapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(RecyclerView parent, View view, int position) {
                Toast.makeText(MainActivity.this,"data="+datas.get(position),Toast.LENGTH_SHORT).show();
            }
        });
//        //设置recyclerview适配器
//        adapter = new MyRecyclerViewAdapter(MainActivity.this,datas);
//        recyclerview.setAdapter(adapter);
//        //LayoutManager
//        recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
        recyclerview.scrollToPosition(datas.size()-1);
//        //添加RecyclerView的分割线
//        recyclerview.addItemDecoration(new DividerListItemDecoration(MainActivity.this,DividerListItemDecoration.VERTICAL_LIST));
//
//        //设置点击某条的监听
//        adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
//            @Override
//            public void onItemClick(View view, String data) {
//                Toast.makeText(MainActivity.this,"data="+data,Toast.LENGTH_SHORT).show();
//            }
//        });
//        //设置动画
//        recyclerview.setItemAnimator(new DefaultItemAnimator());
    }

    private void initView() {
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_delete = (Button) findViewById(R.id.btn_delete);
        btn_list = (Button) findViewById(R.id.btn_list);
        btn_grid = (Button) findViewById(R.id.btn_grid);
        btn_flow = (Button) findViewById(R.id.btn_flow);
        recyclerview = (RecyclerView) findViewById(R.id.recyclerview);
        //设置点击事件
        btn_add.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
        btn_list.setOnClickListener(this);
        btn_grid.setOnClickListener(this);
        btn_flow.setOnClickListener(this);
    }

    private void initData() {
        //准备数据集合
        datas = new ArrayList<>();
        for (int i=0;i<100;i++){
            datas.add("Content_"+i);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_add:
//                adapter.addData(0,"New_Content");
                adapter.insert("New_Content",0);
                recyclerview.scrollToPosition(0);
                break;
            case R.id.btn_delete:
//                adapter.removeData(0);
                adapter.delete(0);
                break;
            case R.id.btn_list:
                //设置List类型效果
                recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
                break;
            case R.id.btn_grid:
                //设置Grid类型效果
                recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this,2,GridLayoutManager.VERTICAL,true));
                recyclerview.scrollToPosition(datas.size()-1);
                break;
            case R.id.btn_flow:
                //设置瀑布流效果
                recyclerview.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
                break;
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.recyclerview.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="添加"
            android:textAllCaps="false" />
        <Button
            android:id="@+id/btn_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="删除"
            android:textAllCaps="false" />
        <Button
            android:id="@+id/btn_list"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="List"
            android:textAllCaps="false" />
        <Button
            android:id="@+id/btn_grid"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Grid"
            android:textAllCaps="false" />
        <Button
            android:id="@+id/btn_flow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="flow"
            android:textAllCaps="false" />
    </LinearLayout>

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

</LinearLayout>

item_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:padding="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#22000000"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ico_jiechu" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:text="Content"
            android:textAllCaps="false"
            android:textColor="#000000" />
    </LinearLayout>
</RelativeLayout>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RecyclerView 的复用问题是指在列表滚动时,旧的 item 会被回收并重新用于新的 item,以提高性能和节省资源。这种复用机制可以避免频繁创建和销毁大量的 View 对象,从而减少内存占用和提高滚动的流畅性。 RecyclerView 的复用机制是通过 ViewHolder 模式实现的。ViewHolder 是一个包含了列表项视图的容器,它会缓存列表项中的子视图的引用,避免频繁地查找子视图。当列表项滚出屏幕时,ViewHolder 持有的子视图会被回收,然后用于新的列表项。 在 RecyclerView 中,有两个重要的方法与复用机制相关: 1. onCreateViewHolder(): 该方法用于创建 ViewHolder 对象。在该方法中,可以通过 LayoutInflater 实例化列表项的布局,并将布局传递给 ViewHolder 构造函数。 2. onBindViewHolder(): 该方法用于将数据绑定到 ViewHolder 中的视图上。在该方法中,可以根据当前位置获取对应的数据,并将数据设置给 ViewHolder 中的子视图。 通过正确使用 ViewHolder 模式,可以避免频繁创建和销毁 View 对象,提高列表的滚动性能。然而,由于复用机制的存在,也可能引发一些问题,例如数据错乱、状态混乱等。为了解决这些问题,需要在 onBindViewHolder() 方法中正确绑定数据,并在需要保存和恢复状态的情况下进行相应的处理。 总之,RecyclerView 的复用机制通过 ViewHolder 模式实现,可以提高列表的性能和滚动的流畅性。但在使用过程中,需要注意正确绑定数据和处理状态,以避免出现问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值