RecyclerView的基本使用方法
来源:互联网 发布:如果世上不再有猫 知乎 编辑:程序博客网 时间:2024/05/17 20:00
作为ListView的豪华加强版,Android支持库中的RecyclerView具有诸多优点。
本篇博客主要用于记录RecyclerView的基本使用方法。
当然在阅读后文前,最好对ListView及对应ViewHolder的使用有一定的了解。
一、概述
RecyclerView的关键类主要有三个,包括RecyclerView、RecyclerView.ViewHolder和RecyclerView.Adpter。
其中:
ViewHolder的作用与使用ListView时,定义的ViewHolder一致,主要用于容纳Item View的视图。
Adapter用于创建必要的ViewHolder,同时将视图和具体的数据绑定在一起。
RecyclerView需要显示视图对象时,就会去调用对应Adapter的接口,整个过程包括以下步骤:
1、调用Adapter的getItemCount方法,询问数据列表中包含多少个对象。
2、调用Adapter的createViewHolder方法,创建ViewHolder及ViewHolder要显示的视图。
3、调用Adapter的onBindViewHolder方法,将具体位置的数据与视图绑定起来,即使用视图来显示数据。
与ListView使用ViewHolder的情况一致,RecyclerView不会频繁调用createViewHolder创建ViewHolder。
当创建的ViewHolder足够多时,RecyclerView就可以回收利用旧的ViewHolder,并利用onBindViewHolder将其与
新的数据绑定,达到节约时间和内存的目的。
了解了基本的原理后,我们来看一下RecyclerView使用的例子。
二、使用方法
1、RecyclerView
RecyclerView定义于com.android.support:recyclerview-v7中,使用时需要添加该库。
使用RecyclerView时的布局类似下图:
<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/crime_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
在界面中加载RecyclerView的方式很简单,如下面代码所示:
public class CrimeListFragment extends Fragment { ............ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //R.layout.fragment_crime_list为定义了RecyclerView的布局文件id View v = inflater.inflate(R.layout.fragment_crime_list, container, false); mCrimeRecyclerView = (RecyclerView) v.findViewById(R.id.crime_recycler_view); //必须为RecyclerView设置LayoutManager //LayoutManager将负责定义屏幕的滚动行为、定位视图等 //可以是LinearLayoutManager、GridLayoutManager等 //例如,设置格型为mCrimeRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3)); mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); ............ //RecyclerView需要显示的数据 CrimeLab crimeLab = CrimeLab.get(getActivity().getApplicationContext()); //创建RecyclerView.Adapter mAdapter = new CrimeAdapter(crimeLab.getCrimes()); //设置Adpter mCrimeRecyclerView.setAdapter(mAdapter); return v; }}
从上面的代码可以看出,RecyclerView在使用时,最主要的还是设置LayoutManager及对应的Adapter。
2、RecyclerView.Adapter
我们再看看Adapter实现的例子:
//继承模板对象,参数为ViewHolder private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> { private List<Crime> mCrimes; //创建的时候,绑定具体的数据 public CrimeAdapter(List<Crime> crimes) { mCrimes = crimes; } @Override //onCreateViewHolder被调用时,创建具体的视图及对应的ViewHolder public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) { //利用LayoutInflater创建出具体的视图 LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); View view = layoutInflater.inflate(R.layout.list_item_crime, parent, false); //让ViewHolder持有视图 return new CrimeHolder(view); } @Override //让视图显示具体的数据 public void onBindViewHolder(CrimeHolder holder, int position) { //这里是将显示工作丢给了ViewHolder holder.bindCrime(mCrimes.get(position), position); } @Override public int getItemCount() { //返回数据的长度 return mCrimes.size(); } }
Adpter这部分代码还是比较简单的,最主要的就是:
1、通过onCreateViewHolder,创建出视图给ViewHolder持有。
2、将position对应的数据,递交给ViewHolder持有的视图显示。
当数据发生变化时,可以使用Adapter的notifyDataSetChanged接口刷新整个界面;
或者使用notifyItemChanged(int position)方法刷新具体的ItemView。
3、RecyclerView.ViewHolder
最后看看ViewHolder实现的例子:
private class CrimeHolder extends RecyclerView.ViewHolder { ................ //ViewHolder定义成员变量保存Item View中不同的组件 public CrimeHolder(View itemView) { super(itemView); .............. mTitleTextView = (TextView) itemView.findViewById( R.id.list_item_crime_title_text_view); mDateTextView = (TextView) itemView.findViewById( R.id.list_item_crime_date_text_view); mSolvedCrimeCheckBox = (CheckBox) itemView.findViewById( R.id.list_item_crime_solved_check_box); } //将数据显示在不同的组件上 public void bindCrime(Crime crime, int position) { mCrime = crime; mPosition = position; mTitleTextView.setText(crime.getTitle()); mDateTextView.setText(crime.getDateString()); mSolvedCrimeCheckBox.setChecked(crime.isSolved()); } }
ViewHolder的实现也极其的简单,其实就是用成员变量来持有视图中的组件。
在需要显示数据时,就将数据添加到不同的视图中。
以上就是RecyclerView的基本用法,在了解ListView使用规则的基础上,还是很好理解的。
三、可能遇到的异常
02-21 17:46:25.772 E/AndroidRuntime(30306): Process: stark.a.is.zhang.photogallery, PID: 3030602-21 17:46:25.772 E/AndroidRuntime(30306): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 69(offset:69).state:90..............
自己写了一个应用,进行以下操作:
1、在后台更新RecyclerView对应数据的下载地址;
2、发送消息到前台,更新RecyclerView;
3、在RecyclerView绑定具体的视图时,进行实际的下载工作。
4、下载完毕时,通知主线程加载新图片。
起初,我的代码是这样写的:
//开始更新RecyclerView的数据private void reloadPictureAfterQueryChange() { mPage = 0; mThumbnailDownloader.clearQueue(); mLastPosition = 0; //mGalleryItems与RecyclerView绑定 //这里先清空旧有数据 mGalleryItems.clear(); showDialog(); //这里开始重新生成新的mGalleryItems数据 startURLLoader(buildLoaderArgs());}
当界面来回滑动后,上述接口被调用时,就概率性的抛出上面提到的异常。
导致这个问题发生的根本原因是,mGalleryItems.clear后,
RecyclerView绑定的数据发生了改变,但没有收到通知。
遇到这种问题,需要进行以下修改:
private void reloadPictureAfterQueryChange() { mPage = 0; mThumbnailDownloader.clearQueue(); mLastPosition = 0; //记录旧有数据大小 int oldSize = mGalleryItems.size(); mGalleryItems.clear(); //通知RecyclerView,数据被移除了 mPhotoRecyclerView.getAdapter().notifyItemRangeRemoved(0, oldSize); showDialog(); startURLLoader(buildLoaderArgs()); }
同样,当RecyclerView的数据增加、改变时,也要及时调用其Adapter的notifyDataSetChanged、notifyItemChanged等接口。
总之,就是让RecyclerView明确数据的变化。
- RecyclerView的基本使用方法
- RecyclerView的基本使用方法
- RecyclerView基本使用方法
- RecyclerView 使用方法总结(一):RecyclerView的基本用法,及实现ListView
- RecyclerView的使用方法
- RecyclerView的使用方法
- RecyclerView 的简单使用方法
- RecyclerView的基本用法
- RecyclerView的基本使用
- RecyclerView的基本创建
- RecyclerView的基本用法
- RecyclerView的基本使用
- RecyclerView的基本用法
- RecyclerView的基本使用
- RecyclerView的基本使用
- RecyclerView的基本用法
- RecyclerView的基本用法
- RecyclerView的基本使用
- Android实用小特效
- PHP上传文件以及文件操作
- LINUX命令自动补全
- 75. Sort Colors
- java内存模型
- RecyclerView的基本使用方法
- 【Java基础知识】IO流--内存操作流ByteArrayInputStream、ByteArrayOutputStream
- 自制3D显示引擎六:填充三角形
- 最近在做微信公众号支付功能,iOS正常唤起微信支付并支付成功;android唤不起微信支付,显示失败。
- Git 使用
- ckermit
- stylus装不上--错误提示解决办法---vue视频
- Spring的依赖注入
- Swift 蒙版操作指引