RecycleView简单总结
基础知识
下拉加载更多
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挡住的问题解决
- 原因分析:
RecycleView
和Toolbar
都是放置在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作为单位进行回收。