一、概念
从Android 5.0开始,谷歌公司推出了一个用于展示大量数据的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的出现会让很多开源项目被废弃,例如横向滚动的ListView、横向滚动的GridView、瀑布流控件,因为RecyclerView能够实现所有这些功能。
二、特点
- RecyclerView封装了ViewHolder的回收复用,也就是说RecyclerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的逻辑被封装了,写起来更加简单,并且直接省去了ListView中convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
- 提供了一种插拔式的体验,高度解耦,非常灵活,RecyclerView专门抽取出了相应的类来控制Item的显示,使其扩展性非常强。
- 设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式。例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的是StaggeredGridLayoutManager等),也就是说RecyclerView不再拘泥于ListView的线性展示方式,它也可以实现GridView等多种效果。
- 可设置Item的间隔样式(可绘制),通过继承RecyclerView的ItemDecoration这个类,然后针对自己的业务需求去编写代码。
- 可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecyclerView有其自己默认的实现。
- 关于Item的点击和长按事件,需要用户自己去实现。
ListView相比RecyclerView,有一些优点:
- addHeaderView()、addFooterView()添加头视图和尾视图。
- 通过"android:divider"设置自定义分割线。
- setOnItemClickListener()和setOnItemLongClickListener()设置点击事件和长按事件。
这些功能在RecyclerView中都没有直接的接口,要自己实现,虽然实现起来也很简单。
RecyclerView相比ListView,有一些优点:
- 默认已经实现了View的复用,不需要类似if(convertView == null)的实现,而且回收机制更加完善。
- 默认支持局部刷新。
- 容易实现添加item、删除item的动画效果。
- 容易实现拖拽、侧滑删除等功能。
RecyclerView是一个插件式的实现,对各个功能进行解耦,从而扩展性比较好。
三、基本使用
//build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.sourcecodetest"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
}
//Fruit
public class Fruit {
private String name;
private int imageId;
public Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}
//fruit_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
//FruitAdapter
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private static final String TAG = "FruitAdapter";
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view) {
super(view);
fruitView = view;
fruitImage = view.findViewById(R.id.fruit_image);
fruitName = view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Log.d(TAG, "zwm, onCreateViewHolder, viewType: " + viewType);
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fruit_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Log.d(TAG, "zwm, 你点击了View: " + fruit.getName());
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Log.d(TAG, "zwm, 你点击了图片: " + fruit.getName());
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
Log.d(TAG, "zwm, onBindViewHolder, position: " + position + ", fruit: " + fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
//activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
//MainActivity
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
initFruits();
RecyclerView recyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager= new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits() {
Fruit fruit = new Fruit("苹果", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("香蕉", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("西瓜", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("龙眼", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("荔枝", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("樱桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("核桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("橙子", R.drawable.ic_launcher);
fruitList.add(fruit);
}
}
//输出log
2020-01-20 15:24:17.578 6404-6404/? D/MyApplication: zwm, onCreate
2020-01-20 15:24:17.803 6404-6404/? D/MainActivity: zwm, onCreate
2020-01-20 15:24:17.969 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:17.979 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 0, fruit: 苹果
2020-01-20 15:24:17.983 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:17.989 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 1, fruit: 香蕉
2020-01-20 15:24:17.991 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:17.996 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 2, fruit: 西瓜
2020-01-20 15:24:17.998 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:18.003 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 3, fruit: 龙眼
2020-01-20 15:24:18.006 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:18.010 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 4, fruit: 荔枝
2020-01-20 15:24:18.013 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:18.021 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 5, fruit: 樱桃
2020-01-20 15:24:18.023 6404-6404/? D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:18.028 6404-6404/? D/FruitAdapter: zwm, onBindViewHolder, position: 6, fruit: 核桃
2020-01-20 15:24:20.364 6404-6404/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 15:24:20.370 6404-6404/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder, position: 7, fruit: 橙子
2020-01-20 15:24:28.299 6404-6404/com.example.sourcecodetest D/FruitAdapter: zwm, 你点击了View: 西瓜
2020-01-20 15:24:34.295 6404-6404/com.example.sourcecodetest D/FruitAdapter: zwm, 你点击了图片: 荔枝
四、LayoutManager
LayoutManager负责RecyclerView的布局,其中包含了Item View的获取与回收。
RecyclerView提供了三种布局管理器:
- LinearLayoutManager:以垂直或者水平列表方式展示Item。
- GridLayoutManager:以网格方式展示Item。
- StaggeredGridLayoutManager:以瀑布流方式展示Item。
GridLayoutManager常用构造方法:
//spanCount,每列或者每行的item个数,设置为1,就是列表样式
//该构造函数默认是竖直方向的网格样式
GridLayoutManager(Context context, int spanCount)
//spanCount,每列或者每行的item个数,设置为1,就是列表样式
//网格样式的方向,水平(OrientationHelper.HORIZONTAL)或者竖直(OrientationHelper.VERTICAL)
//reverseLayout,是否逆向,true:布局逆向展示,false:布局正向显示
GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout)
StaggeredGridLayoutManager常用构造方法:
//spanCount代表每行或每列的Item个数,orientation代表列表的方向,竖直或者水平
StaggeredGridLayoutManager(int spanCount, int orientation)
五、Item Decoration & Item Animator
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private RecyclerView recyclerView;
private FruitAdapter adapter;
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
initFruits();
recyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this, RecyclerView.VERTICAL));
recyclerView.setItemAnimator(new DefaultItemAnimator());
adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits() {
Fruit fruit = new Fruit("苹果", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("香蕉", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("西瓜", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("龙眼", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("荔枝", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("樱桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("核桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("橙子", R.drawable.ic_launcher);
fruitList.add(fruit);
}
}
六、HeaderView & FooterView
//fruit_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
//header_item.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">
<TextView
android:id="@+id/header_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="This is header item"/>
</RelativeLayout>
//footer_item.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">
<TextView
android:id="@+id/footer_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="This is footer item"/>
</RelativeLayout>
//FruitAdapter
public class FruitAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "FruitAdapter";
private static final int HEADER = 0;
private static final int CONTENT = 1;
private static final int FOOTER = 2;
private List<Fruit> mFruitList;
private static class ContentViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ContentViewHolder(View view) {
super(view);
fruitView = view;
fruitImage = view.findViewById(R.id.fruit_image);
fruitName = view.findViewById(R.id.fruit_name);
}
}
private static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
}
private static class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Log.d(TAG, "zwm, onCreateViewHolder, viewType: " + viewType);
if(viewType == HEADER) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.header_item, parent, false);
final HeaderViewHolder holder = new HeaderViewHolder(view);
return holder;
} else if(viewType == FOOTER) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.footer_item, parent, false);
final FooterViewHolder holder = new FooterViewHolder(view);
return holder;
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fruit_item, parent, false);
final ContentViewHolder holder = new ContentViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Log.d(TAG, "zwm, 你点击了View: " + fruit.getName());
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Log.d(TAG, "zwm, 你点击了图片: " + fruit.getName());
}
});
return holder;
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(holder instanceof HeaderViewHolder) {
Log.d(TAG, "zwm, onBindViewHolder HeaderViewHolder, position: " + position);
} else if(holder instanceof FooterViewHolder) {
Log.d(TAG, "zwm, onBindViewHolder FooterViewHolder, position: " + position);
} else {
int index = position - 1;
Fruit fruit = mFruitList.get(index);
((ContentViewHolder)holder).fruitImage.setImageResource(fruit.getImageId());
((ContentViewHolder)holder).fruitName.setText(fruit.getName());
Log.d(TAG, "zwm, onBindViewHolder ContentViewHolder, position: " + position + ", index: " + index + ", fruit: " + fruit.getName());
}
}
@Override
public int getItemCount() {
int itemCount = getContentItemCount() + 2;
Log.d(TAG, "zwm, getItemCount: " + itemCount);
return itemCount;
}
public int getContentItemCount(){
int contentItemCount = mFruitList.size();
Log.d(TAG, "zwm, getContentItemCount: " + contentItemCount);
return contentItemCount;
}
@Override
public int getItemViewType(int position) {
int itemViewType;
if(position == 0){
itemViewType = HEADER;
} else if(position == getContentItemCount() + 1){
itemViewType = FOOTER;
} else{
itemViewType = CONTENT;
}
Log.d(TAG, "zwm, getItemViewType: " + itemViewType);
return itemViewType;
}
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private RecyclerView recyclerView;
private FruitAdapter adapter;
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
initFruits();
recyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this, RecyclerView.VERTICAL));
recyclerView.setItemAnimator(new DefaultItemAnimator());
adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits() {
Fruit fruit = new Fruit("苹果", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("香蕉", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("西瓜", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("龙眼", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("荔枝", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("樱桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("核桃", R.drawable.ic_launcher);
fruitList.add(fruit);
fruit = new Fruit("橙子", R.drawable.ic_launcher);
fruitList.add(fruit);
}
}
//输出log
2020-01-20 19:56:25.254 28840-28840/? D/MyApplication: zwm, onCreate
2020-01-20 19:56:26.751 28840-28840/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-20 19:56:27.628 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.628 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.628 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.629 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.629 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.629 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.629 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 0
2020-01-20 19:56:27.629 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 0
2020-01-20 19:56:27.886 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder HeaderViewHolder, position: 0
2020-01-20 19:56:27.890 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.890 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.890 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.890 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.890 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.904 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 1, index: 0, fruit: 苹果
2020-01-20 19:56:27.909 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.909 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.909 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.909 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.909 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.916 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 2, index: 1, fruit: 香蕉
2020-01-20 19:56:27.919 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.919 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.919 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.919 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.919 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.926 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 3, index: 2, fruit: 西瓜
2020-01-20 19:56:27.929 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.929 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.929 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.929 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.929 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.935 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 4, index: 3, fruit: 龙眼
2020-01-20 19:56:27.938 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.938 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.938 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.938 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.938 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.944 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 5, index: 4, fruit: 荔枝
2020-01-20 19:56:27.947 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.947 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.947 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.947 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.948 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.953 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 6, index: 5, fruit: 樱桃
2020-01-20 19:56:27.956 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.956 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:27.956 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:27.956 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:27.956 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:27.963 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 7, index: 6, fruit: 核桃
2020-01-20 19:56:30.637 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.637 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:30.637 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.637 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:30.637 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 1
2020-01-20 19:56:30.644 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder ContentViewHolder, position: 8, index: 7, fruit: 橙子
2020-01-20 19:56:30.651 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.651 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:30.651 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.651 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:30.665 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.665 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:30.665 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.665 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 1
2020-01-20 19:56:30.683 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.683 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:30.683 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.683 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 2
2020-01-20 19:56:30.683 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onCreateViewHolder, viewType: 2
2020-01-20 19:56:30.689 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, onBindViewHolder FooterViewHolder, position: 9
2020-01-20 19:56:30.697 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.697 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemCount: 10
2020-01-20 19:56:30.697 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getContentItemCount: 8
2020-01-20 19:56:30.697 28840-28840/com.example.sourcecodetest D/FruitAdapter: zwm, getItemViewType: 2