以前面试的时候说自己做过什么巴拉巴拉的,然后提到了在创建列表视图的时候使用了recycleView,然后就是自己挖坑自己填被面试官问到recycleView的优缺点,因为当时就是看了看使用方法然后没有进行系统的套路概括,当时面试官的表情应该是觉得我回答的不够套路。。。好吧那就总结一下吧
RecyclerView是materials design中的组件之一,相应的还有CardView、Palette(Palette是一个可以从图片(Bitmap)中提取颜色的帮助类)等。按名字来说它主要的特点就是复用。我们知道,Listview中的Adapter中可以实现ViewHolder的复用RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView、GridView以及瀑布流的效果。
乍一看recycleView就是List的升级版本可以更加方便实现横纵列表,还有看起来比较灵性的瀑布流,它属于一种新的视图组,目标是为任何基于适配器的视图提供相似的渲染方式。嗯...进入干货阶段
添加依赖
compile 'com.android.support:recyclerview-v7:24.2.1'
然后在XML文件的布局里面进行添加
<android.support.v7.widget.RecyclerView
android:id="@+id/rlv"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
接下来就是三要素了
(1)、LayoutManager
(2)、RecyclerView.Adapter
(3)、ItemAnimator
LayoutManager:通过这位管理员可以将你的RecycleView设置成横向滑动的,纵向滑动的九宫格的还有瀑布流样式的
//参数一:上下文参数二:定义了常量选择整体的方向参数三:Boolean值正序展示FALSE和反序展示TRUE
//线性布局管理器,布局效果类似ListView
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
//九宫格布局,参数二:方向是纵向表示几列(参数三)横向表示几行
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,2,GridLayoutManager.VERTICAL,false);
//瀑布流布局,参数二:表示行列
RecyclerView.LayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
RecyclerView.Adapter这个适配器吧他自己封装好了一个低耦合的ViewHolder嗯就是这样的(很套路了)
//2.设置数据适配器
RecyclerView.Adapter adapter = new MyAdapter();
recyclerView.setAdapter(adapter);
class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{
//当没有可以复用的View时,调用该方法
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = View.inflate(parent.getContext(),R.layout.recyler_item,null);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
//绑定数据到控件
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//设置图片背景
holder.imgView.setBackgroundResource(iconsV[position]);
//设置TextView
holder.tv.setText("position "+position);
}
//条目的个数
@Override
public int getItemCount() {
return iconsV.length;
}
}
class MyViewHolder extends RecyclerView.ViewHolder{
private final ImageView imgView;
private final TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
imgView = (ImageView) itemView.findViewById(R.id.img);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
//理解RecyclerView.Adapter对比BaseAdapter的getView的实现
// abstract class ListViewBaseAdapter extends BaseAdapter{
// @Override
// public View getView(int position, View convertView, ViewGroup parent) {
// ViewHolder holder;
// if(convertView == null){
// convertView = View.inflate(parent.getContext(),R.layout.item,null);
// holder.tv = ;
// holder.iv = ;
// }else{
// holder = convertView.getTag();
// }
// //设置数据
// holder.tv.setText();
// return null;
// }
// }
}
ItemAnimator老实说我没用过这个效果所以就百度一下吧
简单来说是会根据适配器上收到的相关通知去动画的显示组件的修改,添加和删除等。它会自动添加和移除item的动画。自带的默认效果也不错,已经非常好了。
然后进入正经总结
优点:
RecyclerView本身它是不关心视图相关的问题的,由于ListView的紧耦合的问题,google的改进就是RecyclerView本身不参与任何视图相关的问题。它不关心如何将子View放在合适的位置,也不关心如何分割这些子View,更不关心每个子View各自的外观。更进一步来说就是RecyclerView它只负责回收和重用的工作,这也是它名字的由来。
所有关于布局、绘制和其他相关的问题,也就是跟数据展示相关的所有问题,都被委派给了一些”插件化”的类来处理。这使得RecyclerView的API变得非常灵活。你需要一个新的布局么?接入另一个LayoutManager就可以了!你想要不同的动画么?接入一个新的ItemAnimator就可以了,诸如此类等等。
缺点:
在RecyclerView中,没有一个onItemClickListener方法。所以目前在适配器中处理这样的事件比较好。如果想要从适配器上添加或移除条目,需要明确通知适配器。这与先前的notifyDataSetChanged()方法稍微有些不同。具体操作在适配器代码中就可以体现。
整体总结它的几点如下:
Adapter:包装数据集合并且为每个条目创建视图。
ViewHolder:保存用于显示每个数据条目的子View。
LayoutManager:将每个条目的视图放置于适当的位置。
ItemDecoration:在每个条目的视图的周围或上面绘制一些装饰视图。
ItemAnimator:在条目被添加、移除或者重排序时添加动画效果。(这段是抄的懒得写了嘿嘿)
补充一个当recycleView嵌套发生滑动冲突的解决方法
把子布局的recycleView使用RelativeLayout布局包裹然后设置RelativeLayout的
descendantFocusability属性
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<android.support.v7.widget.RecyclerView
android:id="@+id/rlv_conversion"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
大概这个样子,然后接着补充一下descendantFocusability属相的三种设置
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
在item的根布局中加入android:descendantFocusability=”blockDescendants”属性即可以解决子控件抢占父控件的焦点问题。