上一篇文章说了 Paging2.0的基本使用
https://blog.csdn.net/Leo_Liang_jie/article/details/109473099
其实 Paging3.0早出来,而且功能会更加强大,比如下面:
1:为 Kotlin 协程和流程提供一流更好的支持
2:分页数据缓存到内存中,保证应用在处理页面数据的时候,更有效的使用系统资源
等等
原理这个2.0文章已经说过了,这边直接上代码,
升级依赖到:3.0
implementation "androidx.paging:paging-runtime:3.0.0-alpha09"
读者可以把Android Studio 升级到最新版本,把鼠标放在依赖处,Gradle会提醒最新的版本是:
好了,直接上Adapter 代码,2.0继承的是 PagedListAdapter,3.0继承的是:PagingDataAdapter,除了这个之外,其他写法没区别
class MyPaged3ListAdapter extends PagingDataAdapter {
public MyPaged3ListAdapter() {
// 通过 构造方法 设置 DiffUtil.ItemCallback
super(DIFF_CALLBACK);
}
private static DiffUtil.ItemCallback DIFF_CALLBACK =
new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(MyDataBean oldConcert, MyDataBean newConcert) {
// 比较两个Item数据是否一样的,可以简单用 Bean 的 hashCode来对比
return oldConcert.hashCode() == newConcert.hashCode();
}
@Override
public boolean areContentsTheSame(MyDataBean oldConcert,
MyDataBean newConcert) {
// 写法基本上都这样写死即可
return oldConcert.equals(newConcert);
}
};
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_my, parent, false);
return new MyViewHolder(inflate);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// getItem() 是 PagedListAdapter 内部方法,通过此方法可以获取到对应位置Item 的数据
holder.bindData(getItem(position));
}
}
再看DataSource,2.0用的 PositionalDataSource,3.0用的是 PagingSource
class MyPagingSource : PagingSource() {
/**
* params.key 是取 当前列表的起始节点
* params.loadSize 是获取当前列表的长度
* */
override suspend fun load(params: LoadParams): LoadResult {
val startPosition = params.key ?: 0
val loadSize = params.loadSize
// 加载的数据
val data = getData(startPosition, loadSize)
return LoadResult.Page(
data,
// 往上加载的Key ,如果不可以往上加载就null
null,
// 加载下一页的key 如果传null就说明到底了
startPosition + data.size
)
}
/**
* 模拟网络获取数据
* */
private fun getData(startPosition: Int, pageSize: Int): MutableList {
val list = mutableListOf()
for (i in startPosition until startPosition + pageSize) {
list.add(MyDataBean(i))
}
return list
}
}
创建Repository,2.0是创建 DataSource.Factory,3.0是创建自定义类,把 Pager 和PagingSource绑定设置
class MyRepository {
/**
* pageSize = 20 设置每一页加载长度,
* 和 PagingSource 的 params.loadSize对应
* */
fun getData() = Pager(PagingConfig(pageSize = 20)) {
MyPagingSource()
}
}
创建ViewModel,把Repository 和 LiveData 绑定
class MyPaging3ViewModel : ViewModel() {
private val myRepository: MyRepository by lazy { MyRepository() }
fun getData() = myRepository.getData().asLiveData()
}
看下Activity,和2.0没啥区别,就是 Adapter.submitData 需要在协程里面
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.layoutManager = LinearLayoutManager(this)
val myPagedListAdapter = MyPaged3ListAdapter()
recyclerView.adapter = myPagedListAdapter
/**
* ViewModel 绑定 Activity 生命周期
* */
val myViewModel = ViewModelProviders.of(this).get(MyPaging3ViewModel::class.java)
/**
* ViewModel 感知数据变化,更新 Adapter 列表
* Adapter.submitData 这是一个用 suspend 修饰的方法,所以需要开启一个有生命周期的协程
* */
myViewModel.getData().observe(this, Observer {
lifecycleScope.launch {
myPagedListAdapter.submitData(it)
}
})
}
}
运行效果和 2.0一样,测试没问题
上面代码亲测没问题,有问题请留言。
github连接:
https://github.com/LeoLiang23/PagingDemo.git
下面链接是我看过比较好的Paging的文章,也可以参考一下
https://mp.weixin.qq.com/s/qBxhtgjLluUZsHCinNHUAQ