RecyclerView用法老忘,写一个blog,以后再用的时候有不清楚的时候就不用翻好多资料了!芜湖。

代码部分

layout

两个layout,一个存有Recyclerview,另一个是需要加载在每个position的item。

这个存放RecyclerView。

1
2
3
4
5
6
7
8
9
10
11
12
<?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="match_parent">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>

</RelativeLayout>

发现已经不用导入v7包了,也不用添加依赖,真不戳!

然后是每个item:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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"
android:padding="10dp">

<TextView
android:id="@+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"/>

</RelativeLayout>

Activity

两个activity,一个显示RV,另一个适配器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MainActivity extends AppCompatActivity {

private RecyclerView mRvMain;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRvMain = findViewById(R.id.recycle_view);
mRvMain.setLayoutManager(new LinearLayoutManager(MainActivity.this));
// mRvMain.addItemDecoration(new MyDecoration()); // 自定义边框分隔线
mRvMain.setAdapter(new RecyclerviewAdapter(MainActivity.this));
}

// class MyDecoration extends RecyclerView.ItemDecoration{
// @Override
// public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
// super.getItemOffsets(outRect, view, parent, state);
// outRect.set(0,0,0,0);
// }
// }

}

Adapter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class RecyclerviewAdapter extends RecyclerView.Adapter<RecyclerviewAdapter.RecyclerViewHolder> {

private Context mContext;

public RecyclerviewAdapter(Context context){
this.mContext = context;
}


@NonNull
@Override
public RecyclerviewAdapter.RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new RecyclerViewHolder(LayoutInflater.from(mContext).inflate(R.layout.recycle_view_item, parent, false));
}

@Override
public void onBindViewHolder(@NonNull RecyclerviewAdapter.RecyclerViewHolder holder, int position) {
holder.tv.setText("test"); // 绑定
// holder.itemView.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// // 点击事件
// }
// });
// holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
// @Override
// public boolean onLongClick(View view) {
// // 长按点击事件
// return false;
// }
// });
}
}

@Override
public int getItemCount() {
return 10; // item个数
}

class RecyclerViewHolder extends RecyclerView.ViewHolder{

private TextView tv;

public RecyclerViewHolder(@NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.item);
}
}

}

浅析

RV的视图复用管理更好,能使用列表网格和瀑布流,API中封装了好多实用功能,但是使用稍微麻烦,没有onItemClickListener等监听事件,要自己写。

RecyclerView的缓存

rv缓存分为四级,scrap,catche,ViewCacheExtension,RecycledViewPool。缓存中的ViewHolder都不需要重新创建视图。

Scrap


scrap下的缓存又分为两类,一类mAttachedScrap缓存正在显示的ViewHolder,一类mChangedScrap缓存发生变化的ViewHolder,mChangedScrap中的ViewHolder会被移动到RecycledViewPool中。

cache


cache,即mCachedViews,缓存从屏幕中移除但是可能会被再次显示的ViewHolder,有大小限制。例如手指向上滑动(向下翻页)时,刚被划出屏幕外的,很有可能存放在mCachedViews中(在大小限制以内)。

ViewCacheExtension


ViewCacheExtension用户自定义的缓存,可以实现一些特殊功能,比如说ViewHolder中某个固定位置,内容是固定的(一些app最上面的广告,position为0时),自定义好缓存后,滑出该位置再回来就不会重新new和bind,而是直接在ViewCacheExtension找。

RecycledViewPool


RecycledViewPool存储各种ViewHolder,需要被重新绑定数据,可能像scrap下mChangedScrap数据有改变所以需要重新绑定,也可能是超出mCachedViews和ViewCacheExtension的数据。

参考文章

真正带你搞懂 RecyclerView 的缓存机制,再也不怕面试被虐了 - 知乎 (zhihu.com)

RecycleView的复用和优化 - 简书 (jianshu.com)