什么是recyclerView?我们常见的可以滑动的,分块的视图样式就可以认为是recyclerView。
比如:
在开发前还需要了解一些概念:
ViewHolder:可以看到recyclerView是以分块的视图形式组织的。分块无论其形状,里面的内容如何,每一个分快称之为ViewHolder。上图中一个title+subtitle的条形分块就是一个ViewHolder。
Adapter:可以确认的是,recyclerView一定是有数据填充的,也一定有一个工具性质的东西能够将数据正确地和每一个ViewHolder绑定,进而渲染其内容。实现这个流程的工具就是Adapter。
知道以上概念之后就可以开发了。
首先在需要展示的view里创建一个recyclerView:
- "1.0" encoding="utf-8"?>
- <androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- tools:context=".MainActivity">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- />
-
- androidx.constraintlayout.widget.ConstraintLayout>
随后在代码中获取其对象:
mRecyclerView = this.findViewById(R.id.recycler_view);
此外,viewHolder的视图也需要自定义
- "1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android" - android:layout_width="match_parent"
- android:layout_height="wrap_content"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/list_item">
-
-
- android:id="@+id/main_title"
- android:layout_width="wrap_content"
- android:layout_height="40dp"
- android:textSize="30sp"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- android:layout_centerVertical="true"
- tools:text="你好"/>
-
-
- android:id="@+id/subtitle"
- app:layout_constraintLeft_toLeftOf="@id/main_title"
- app:layout_constraintTop_toBottomOf="@id/main_title"
- android:layout_marginTop="10dp"
- android:textSize="12sp"
- android:layout_height="20dp"
- android:layout_width="wrap_content"
- android:layout_centerVertical="true"
- tools:text="是的"/>
-
-
2.创建数据类型
为了方便组织代码,我们通常将每个viewHolder中需要用到的数据抽象成一个data object。
- public class ItemDTO {
- public String Title;
- public String subTitle;
- }
这里为了方便,本地mock出一组给recylerView使用的数据(数组)。
- private void mockData() {
- itemDTOList = new ArrayList<>();
- for (int i = 0; i < 20 ;i++) {
- ItemDTO itemDTO = new ItemDTO();
- itemDTO.Title = "title" + i;
- itemDTO.subTitle = "subtitle" + i;
- itemDTOList.add(itemDTO);
- }
- }
3.创建adapter和viewHolder
这是最难的一步,先贴上代码。
- package recyclerview;
-
- import android.util.Log;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.TextView;
-
- import androidx.recyclerview.widget.RecyclerView;
-
- import com.example.myapplication.R;
-
- import java.util.List;
-
- public class ListViewAdapter extends RecyclerView.Adapter
{ - private final static String TAG = "ListViewAdapter";
- // 绑定在recyclerView的数据集
- private final List
mItemDTOList; -
- public ListViewAdapter(List
mItemDTOList) { - this.mItemDTOList = mItemDTOList;
- }
-
- /**
- * 首次创建viewHolder时调用
- * @param parent
- * @param viewType
- * @return
- */
- @Override
- public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- Log.d(TAG, "onCreateViewHolder");
- // 创建viewHolder
- View viewHolder = View.inflate(parent.getContext(), R.layout.list_view_item, null);
- return new ListViewAdapter.viewHolder(viewHolder);
- }
-
- /**
- * 上下滑动recyclerView调用
- * @param holder
- * @param position
- */
- @Override
- public void onBindViewHolder(ListViewAdapter.viewHolder holder, int position) {
- // 给对应位置的viewHolder绑定数据
- holder.bindData(mItemDTOList.get(position));
- }
-
-
- @Override
- public int getItemCount() {
- if (mItemDTOList == null || mItemDTOList.isEmpty()) {
- return 0;
- } else {
- return mItemDTOList.size();
- }
- }
-
- /**
- * viewHolder对象
- */
- public class viewHolder extends RecyclerView.ViewHolder {
- private final TextView mMainTitle;
- private final TextView mSubtitle;
-
- public viewHolder(View itemView) {
- super(itemView);
- mMainTitle = itemView.findViewById(R.id.main_title);
- mSubtitle = itemView.findViewById(R.id.subtitle);
- }
-
- /**
- * 将数据映射到每个viewHolder的视图上
- * @param itemDTO
- */
- public void bindData(ItemDTO itemDTO) {
- mMainTitle.setText(itemDTO.Title);
- mSubtitle.setText(itemDTO.subTitle);
- Log.d(TAG, "bindData: title = " + itemDTO.Title + " , subtitle = " + itemDTO.subTitle);
- }
- }
- }
viewHolder
自定义的viewHolder集成了安卓原生的viewHolder,并自己实现了一个核心方法。
viewHolder有两个任务:
1.初始化viewHolder的视图组件
2.提供数据绑定的方法,将之前定义的data object里的数据设置到视图中。
核心方法:bindData,将data object里的数据设置到视图组件中。
Adapter
自定义的adapter继承了安卓原生的adapter,并重写两个核心方法。
adapter有三个任务:
1.获取到需要绑定到整个recyclerView的数据集。
2.在创建viewHolder时,创建自定义的viewHolder。
3.在绑定数据时,将对应的data object传给对应的viewHolder。
核心方法onCreateViewHolder:
调用时机:每个viewHolder被创建时(不一定每个都创建)
recyclerView有复用viewHolder的机制,即同一个类型的viewHolder不会一直重复创建。尤其是整个recylerView只有一种viewHolder时,在第一次填满整个屏幕后通常就不会再创建viewHolder了,而是通过重复绑定数据来刷新视图,给用户一种不断滑动的感觉。
因此在创建viewHolder时,我们只需要把viewHolder inflate出来,并返回即可。
核心方法onBindViewHolder:
调用时机:每个viewHolder被绑定数据时(每个都被绑数据)
从刚才的描述可以得知,数据绑定这一操作是贯彻在滑动过程中的。该方法调用时会传入当前的viewHolder和当前viewHolder在整个recyclerView的位置。
因此在绑定数据时,我们只需要执行每个viewHolder的bindData即可。
4.设置recylerView
- private void initData() {
- // 填充数据
- mockData();
- // 创建adapter 必须
- ListViewAdapter listViewAdapter = new ListViewAdapter(itemDTOList);
- // 设置recyclerView的排列模式 必须
- LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
- mRecyclerView.setLayoutManager(linearLayoutManager);
- // 设置adapter 必须
- mRecyclerView.setAdapter(listViewAdapter);
- }
recylerView必须设置的两个元素:排列模式和adapter,否则无法正确运行。
-
相关阅读:
Postgres-on conflict do 引起的core宕问题
解决 VS2022 关于 c++17 报错: C2131 表达式必须含有常量值
第60节——使用redux-toolkit实战一个商品列表的增删查改
Grafana+Prometheus 搭建 JuiceFS 可视化监控系统
C++学习笔记--黑马程序员
计算机组成学习-数据的表示和运算总结
ASP.NET Core Web API 接口限流
5G商企专网,助力打造城市生命线“安徽样板”
kaggle机器学习baselines
顺序栈算法库构建
-
原文地址:https://blog.csdn.net/m0_37872216/article/details/136787656