Android--Jetpack--Paging详解

news/2025/2/12 0:50:39/

不尝世间醋与墨,怎知人间酸与苦。

择一业谋食养命,等一运扭转乾坤。

你见过哪些令你膛目结舌的代码技巧?

文章目录

    • 不尝世间醋与墨,怎知人间酸与苦。
    • 择一业谋食养命,等一运扭转乾坤。
    • 你见过哪些令你膛目结舌的代码技巧?
  • 一,定义
  • 二,优点
  • 三,角色
  • 四,PositionalDataSource来源的使用
    • 1,添加依赖
    • 2,创建bean类
    • 3,创建PositionalDataSource来源的数据源
    • 4,创建数据工厂
    • 5,创建ViewModel
    • 6,创建adapter
    • 7,运行效果
  • 五,ItemKeyedDataSource来源的使用
    • 1,创建数据仓库
    • 2,创建ItemKeyedDataSource
    • 3,创建YuanZhenDataSourceFactory
  • 六,PageKeyedDataSource来源的使用
    • 1,创建PageKeyedDataSource
    • 2,创建数据工厂

一,定义

在我们的 Android 项目中使用 RecyclerViews 时,我们会显示一个包含很多项目的列表。有时我们有一些用例,比如从手机中获取联系人列表并将其显示在列表中。在列表中一次加载大量数据并不是一项非常有效的任务。为了克服这个问题,我们在 Android 中进行了分页。 Paging就是google为了分页而推出的一个库。Paging库可以帮助您一次加载和显示多个小的数据块,按需载入部分数据可以减少网络宽带和系统资源的使用量。

二,优点

①:分页库可以更加轻松地在应用程序中的Recyclerview逐步和优雅的加载数据
​②:数据请求消耗的网络带宽更少,系统资源更少
​③:即使在数据更新和刷新期间,应用程序仍会继续快速响应用户输入 ​
④:不过多浪费,显示多少就用多少

三,角色

①:DataSource(数据源,包含了多种形式,例如:Room来源,PositionalDataSource来源,PageKeyedDataSource来源,ItemKeyedDataSource来源)
数据源就是数据的来源,可以有多种来源渠道,例如:“网络数据”,“本地数据”,“数据库数据”

②:PagedList(UIModel数据层,通过Factory的方式拿到数据源)
创建 管理 数据源 的工厂,为什么有一个工厂,除了可以去创建数据源之外,为了后续的扩展

③:PagedAdapter(不再是之前使用RecycleView的那种适配器了,而是和Paging配套的PagedListAdapter)
数据模型其实就是 ViewModel,用来管理数据
PagedList: 数据源获取的数据最终靠PagedList来承载。
对于PagedList,我们可以这样来理解,它就是一页数据的集合。
每请求一页,就是新的一个PagedList对象。

④:RecycleView(我们之前一直用的RecycleView,只不过setAdapter的时候,绑定的适配器是 PagedAdapter)
这个Adapter就是一个RecyclerView的Adapter。
不过我们在使用paging实现RecyclerView的分页加载效果,
不能直接继承RecyclerView的Adapter,而是需要继承PagedListAdapter。
LiveData观察到的数据,把感应到的数据 给 适配器,适配器又绑定了 RecyclerView,那么RecyclerView的列表数据就改变了

四,PositionalDataSource来源的使用

1,添加依赖

implementation 'androidx.paging:paging-runtime:2.1.0'

2,创建bean类

public class YuanZhen {private String id;private String name;private String age;public void setId(String id) {this.id = id;}public String getId() {return id;}public void setName(String name) {this.name = name;}public void setAge(String age) {this.age = age;}public String getName() {return name;}public String getAge() {return age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;YuanZhen student = (YuanZhen) o;return id.equals(student.id) &&name.equals(student.name) &&age.equals(student.age);}// 比较的函数@RequiresApi(api = Build.VERSION_CODES.KITKAT)@Overridepublic int hashCode() {return Objects.hash(id, name, age);}
}

3,创建PositionalDataSource来源的数据源

public class YuanZhenDataSource extends PositionalDataSource<YuanZhen> {/*** 加载第一页数据的时候,会执行此函数来完成* 加载初始化数据,加载的是第一页的数据。* 形象的说,当我们第一次打开页面,需要回调此方法来获取数据。*/@Overridepublic void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<YuanZhen> callback) {callback.onResult(getStudents(0, 20), 0, 1000);}/*** 当有了初始化数据之后,滑动的时候如果需要加载数据的话,会调用此方法。*/@Overridepublic void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<YuanZhen> callback) {callback.onResult(getStudents(params.startPosition, params.loadSize));}/*** 数据源,数据的来源(数据库,文件,网络服务器响应  等等)*/private List<YuanZhen> getStudents(int startPosition, int pageSize) {List<YuanZhen> list = new ArrayList<>();for (int i = startPosition; i < startPosition + pageSize; i++) {YuanZhen yuanZhen = new YuanZhen();yuanZhen.setName("袁震:" + i);yuanZhen.setAge("年龄:" + i);list.add(yuanZhen);}return list;}
}

4,创建数据工厂

public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {YuanZhenDataSource yuanZhenDataSource =new YuanZhenDataSource();return yuanZhenDataSource;}
}

5,创建ViewModel

public class YuanZhenViewModel extends ViewModel {private final LiveData<PagedList<YuanZhen>> listLiveData;public YuanZhenViewModel() {YuanZhenDataSourceFactory factory = new YuanZhenDataSourceFactory();// 初始化 ViewModelthis.listLiveData = new LivePagedListBuilder<Integer, YuanZhen>(factory, 20).build();}public LiveData<PagedList<YuanZhen>> getListLiveData() {return listLiveData;}
}

6,创建adapter

public class RecyclerPagingAdapter extends PagedListAdapter<YuanZhen,RecyclerPagingAdapter.MyRecyclerViewHolder> {private static DiffUtil.ItemCallback<YuanZhen> DIFF_STUDNET = newDiffUtil.ItemCallback<YuanZhen>() {// 一般是比较 唯一性的内容, ID@Overridepublic boolean areItemsTheSame(@NonNull YuanZhen oldItem, @NonNull YuanZhen newItem) {return oldItem.getId().equals(newItem.getId());}// 对象本身的比较@Overridepublic boolean areContentsTheSame(@NonNull YuanZhen oldItem, @NonNull YuanZhen newItem) {return oldItem.equals(newItem);}};protected RecyclerPagingAdapter() {super(DIFF_STUDNET);}@NonNull@Overridepublic MyRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);return new MyRecyclerViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull MyRecyclerViewHolder holder, int position) {YuanZhen yuanzhen = getItem(position);// item view 出来了, 分页库还在加载数据中,我就显示 Id加载中if (null == yuanzhen) {holder.tvName.setText("Name加载中");holder.tvAge.setText("age加载中");} else {holder.tvName.setText(yuanzhen.getName());holder.tvAge.setText(yuanzhen.getAge());}}// Item 优化的 ViewHolderpublic static class MyRecyclerViewHolder extends RecyclerView.ViewHolder {TextView tvId;TextView tvName;TextView tvAge;public MyRecyclerViewHolder(View itemView) {super(itemView);tvName = itemView.findViewById(R.id.tv_name); // 名称tvAge = itemView.findViewById(R.id.tv_age); // 性别}}
}

item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20dp"android:layout_weight="1"android:gravity="center"android:layout_marginLeft="5dp"/><TextViewandroid:id="@+id/tv_age"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20dp"android:textColor="@android:color/black"android:layout_weight="1"android:gravity="center"android:layout_marginLeft="5dp"/></LinearLayout>

7,使用

public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;RecyclerPagingAdapter recyclerPagingAdapter;YuanZhenViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView =  findViewById(R.id.recycle_view);recyclerPagingAdapter = new RecyclerPagingAdapter();viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(YuanZhenViewModel.class);// LiveData 观察者 感应更新viewModel.getListLiveData().observe(this, new Observer<PagedList<YuanZhen>>() {@Overridepublic void onChanged(PagedList<YuanZhen> students) {// 再这里更新适配器数据recyclerPagingAdapter.submitList(students);}});recyclerView.setAdapter(recyclerPagingAdapter);recyclerView.setLayoutManager(new LinearLayoutManager(this));}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycle_view"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>

7,运行效果

在这里插入图片描述

五,ItemKeyedDataSource来源的使用

1,创建数据仓库

public class DataRepository {private List<YuanZhen> dataList = new ArrayList<>();public DataRepository() {for (int i = 0; i < 1000; i++) {YuanZhen person = new YuanZhen();person.setName("袁震:" + i);person.setAge("年龄:" + i);dataList.add(person);}}public List<YuanZhen> initData(int size) {return dataList.subList(0, size);}public List<YuanZhen> loadPageData(int page, int size) {int totalPage;if (dataList.size() % size == 0) {totalPage = dataList.size() / size;} else {totalPage = dataList.size() / size + 1;}if (page > totalPage || page < 1) {return null;}if (page == totalPage) {return dataList.subList((page - 1) * size, dataList.size());}return dataList.subList((page - 1) * size, page * size);}
}

2,创建ItemKeyedDataSource

public class CustomItemDataSource extends ItemKeyedDataSource<Integer, YuanZhen> {private DataRepository dataRepository;CustomItemDataSource(DataRepository dataRepository) {this.dataRepository = dataRepository;}// loadInitial 初始加载数据@Overridepublic void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.initData(params.requestedLoadSize);callback.onResult(dataList);}@NonNull@Overridepublic Integer getKey(@NonNull YuanZhen item) {return (int) System.currentTimeMillis();}// loadBefore 向前分页加载数据@Overridepublic void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList);}}// loadAfter 向后分页加载数据@Overridepublic void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList);}}}

3,创建YuanZhenDataSourceFactory

public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {return new CustomItemDataSource(new DataRepository());}
}

六,PageKeyedDataSource来源的使用

1,创建PageKeyedDataSource

public class CustomPageDataSource extends PageKeyedDataSource<Integer, YuanZhen> {private DataRepository dataRepository;CustomPageDataSource(DataRepository dataRepository) {this.dataRepository = dataRepository;}// loadInitial 初始加载数据@Overridepublic void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.initData(params.requestedLoadSize);callback.onResult(dataList, null, 2);}// loadBefore 向前分页加载数据@Overridepublic void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList, params.key - 1);}}// loadAfter 向后分页加载数据@Overridepublic void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList, params.key + 1);}}
}

2,创建数据工厂

public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {return new CustomPageDataSource(new DataRepository());}
}

http://www.ppmy.cn/news/1294986.html

相关文章

损失函数篇 | YOLOv8 引入 Shape-IoU 考虑边框形状与尺度的度量

作者导读&#xff1a;Shape-IoU&#xff1a;考虑边框形状与尺度的度量 论文地址&#xff1a;https://arxiv.org/abs/2312.17663 作者视频解读&#xff1a;https://www.bilibili.com 开源代码地址&#xff1a;https://github.com/malagoutou/Shape-IoU/blob/main/shapeiou.py…

JavaWeb——新闻管理系统(Jsp+Servlet)之jsp新闻修改

java-ee项目结构设计 1.dao:对数据库的访问&#xff0c;实现了增删改查 2.entity:定义了新闻、评论、用户三个实体&#xff0c;并设置对应实体的属性 3.filter&#xff1a;过滤器&#xff0c;设置字符编码都为utf8&#xff0c;防止乱码出现 4.service:业务逻辑处理 5.servlet:处…

SSH端口转发

SSH&#xff1a;Secure Shell&#xff0c;是一种在不安全网络中提供安全连接的协议&#xff0c;通过加密隧道&#xff0c;提供了对远程计算机的访问。 可不仅是一个远程工具&#xff0c;还有多种功能&#xff0c;比如说端口转发&#xff0c;主要分为以下三种类型&#xff1a; 本…

【C++】带你学会使用C++线程库thread、原子库atomic、互斥量库mutex、条件变量库condition_variable

C线程相关知识讲解 前言正式开始C官方为啥要提供线程库thread构造函数代码演示this_threadget_id()yield()sleep_until和sleep_for mutex构造函数lock和unlock上锁全局锁局部锁lambda表达式 try_lock 其他锁时间锁递归版本专用锁recursive_mutex 锁的异常处理lock_guardunique_…

typescript递归处理

typescript是一种类型强约束的语言&#xff0c;一般来讲定义类型时都要明确指定类型的数据结构。而如果数据结构中涉及到不知道基层嵌套的递归时&#xff0c;就会有一些麻烦。 在 https://stackoverflow.com/questions/51657815/recursive-array-type-typescript 有一个回答…

Ubuntu上wps调用zotero的方法

本人电脑Ubuntu22.04 克隆这位大佬的项目&#xff0c;并转到合适的目录下https://github.com/tankwyn/WPS-Zotero 输入命令 unzip WPS-Zotero-main.zip # 解压文件 cd WPS-Zotero-main # 进入目录 ./install.py # 安装文件如果上面的流程全部正常&#xff0c;恭喜成功 如果出现…

11.20 校招 实习 内推 面经

绿*泡*泡&#xff1a; neituijunsir 交流裙 &#xff0c;内推/实习/校招汇总表格&#xff0c;简历修改咨询 1、校招&#xff5c;赛力斯集团2024届校园招聘热招职位盘点 校招&#xff5c;赛力斯集团2024届校园招聘热招职位盘点 2、校招&#xff5c;天津能源投资集团有限公司…

CHS_02.1.1.2+操作系统的特征

CHS_02.1.1.2操作系统的特征 操作系统的四个特征并发这个特征为什么并发性对于操作系统来说是一个很重要的基本特性资源共享虚拟异步性 各位同学 大家好 在这个小节当中 我们会学习 操作系统的四个特征 操作系统有并发 共享 虚拟和异部这四个基本的特征 其中 并发和共享是两个…