在项目中使用RecyclerView已经有很长一段时间了,现在结合RecyclerView源码分析总结一下。
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {
...
final Recycler mRecycler = new Recycler();
private Adapter mAdapter;
private LayoutManager mLayout;
...
public RecyclerView(Context context) {
this(context, null);
}
public RecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
...
}
public void setLayoutManager(LayoutManager layout) {
...
}
...
public void setItemViewCacheSize(int size) {
mRecycler.setViewCacheSize(size);
}
public void addItemDecoration(ItemDecoration decor, int index) {
...
}
...
public static class RecycledViewPool {
...
}
public final class Recycler {
...
}
public abstract static class ViewCacheExtension {
...
}
public static abstract class Adapter {
...
}
public static abstract class LayoutManager {
...
}
public static abstract class ItemDecoration {
...
}
public static abstract class ViewHolder {
...
}
public static abstract class ItemAnimator {
...
}
...
}
public static abstract class Adapter {
...
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
public abstract void onBindViewHolder(VH holder, int position);
public final VH createViewHolder(ViewGroup parent, int viewType) {
TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
final VH holder = onCreateViewHolder(parent, viewType);
holder.mItemViewType = viewType;
TraceCompat.endSection();
return holder;
}
public final void bindViewHolder(VH holder, int position) {
holder.mPosition = position;
if (hasStableIds()) {
holder.mItemId = getItemId(position);
}
holder.setFlags(ViewHolder.FLAG_BOUND,
ViewHolder.FLAG_BOUND | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID
| ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN);
TraceCompat.beginSection(TRACE_BIND_VIEW_TAG);
onBindViewHolder(holder, position);
TraceCompat.endSection();
}
public int getItemViewType(int position) {
return 0;
}
public abstract int getItemCount();
...
}
阅读RecyclerView的源码,发现其Adapter没有任何默认实现,在使用的时候需要自己实现Adapter,三个抽象函数是必须要实现的,getItemViewType函数可根据实际需求进行重载,如果RecyclerView的Item有多种类型,则需要重载,否则默认实现方式就可以了。
public static abstract class ViewHolder {
public final View itemView;
...
public ViewHolder(View itemView) {
if (itemView == null) {
throw new IllegalArgumentException("itemView may not be null");
}
this.itemView = itemView;
}
...
}
正如源码所示,itemView 已经以public 方式存放了,自定义ViewHolder 时,不再需要在重复保存itemView ,项目中需要对itemView 操作(如设置背景、添加事件等),直接使用就可以了。 实际使用的时候,使用自定义的ViewHolder 来替换RecyclerView.Adapter里面的泛型VH。
public void onLayoutChildren(Recycler recycler, State state) {
Log.e(TAG, "You must override onLayoutChildren(Recycler recycler, State state) ");
}
public abstract LayoutParams generateDefaultLayoutParams();
android.support.v7库提供的LayoutManager 默认实现有如下几种:
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.StaggeredGridLayoutManager;
其中,LinearLayoutManager提供类似ListView的功能,可以实现水平或垂直列表,默认为垂直列表。
public class LinearLayoutManager extends RecyclerView.LayoutManager implements
ItemTouchHelper.ViewDropHandler {
public LinearLayoutManager(Context context) {
this(context, VERTICAL, false);
}
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
setOrientation(orientation);
setReverseLayout(reverseLayout);
}
public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes);
setOrientation(properties.orientation);
setReverseLayout(properties.reverseLayout);
setStackFromEnd(properties.stackFromEnd);
}
}
GridLayoutManager 提供类似GradView的功能,实现表格布局。
...
void setRecycledViewPool(RecycledViewPool pool) {
if (mRecyclerPool != null) {
mRecyclerPool.detach();
}
mRecyclerPool = pool;
if (pool != null) {
mRecyclerPool.attach(getAdapter());
}
}
RecycledViewPool getRecycledViewPool() {
if (mRecyclerPool == null) {
mRecyclerPool = new RecycledViewPool();
}
return mRecyclerPool;
}
...
通过上述源码,发现RecycledViewPool使用也非常简单,只需获取任意一个RecyclerView创建的RecycledViewPool,然后分别设置到其他RecyclerView,就可实现共享。
RecyclerView view1 = new RecyclerView(mContext);
LinearLayoutManager layout = new LinearLayoutManager(mContext);
layout.setRecycleChildrenOnDetach(true);
view1.setLayoutManager(layout);
RecyclerView.RecycledViewPool recycledViewPool = view1.getRecycledViewPool();
RecyclerView view2 = new RecyclerView(mContext);
view2.setRecycledViewPool(recycledViewPool);
...
RecyclerView view3 = new RecyclerView(mContext);
view3.setRecycledViewPool(recycledViewPool);
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_recyclerview_test);
...
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(layoutManager);
MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter();
recyclerView.setAdapter(adapter);
...
}
...
public class MyRecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public MyRecyclerViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.name);
}
}
public class MyRecyclerViewAdapter extends RecyclerView.Adapter {
@Override
public MyRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_recyclerview_test_layout, parent, false);
MyRecyclerViewHolder viewHolder = new MyRecyclerViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(MyRecyclerViewHolder holder, int position) {
holder.textView.setText("hello "+position);
}
@Override
public int getItemCount() {
return 3;
}
}
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者郭举军授权发布。