Jetpack Paging3分页库
程序员文章站
2022-06-22 21:44:22
Jetpack Paging3分页库简介分页库可帮助您一次加载和显示一小块数据。按需载入部分数据会减少网络带宽和系统资源的使用量。依赖在app的build.gradle文件中添加依赖:dependencies { ...... def paging_version = "2.1.2" // kotlin使用 paging-runtime-ktx(Java使用 paging-runtime) implementation "androidx.paging:pag...
Jetpack Paging3分页库
简介
分页库可帮助您一次加载和显示一小块数据。按需载入部分数据会减少网络带宽和系统资源的使用量。
依赖
在app的build.gradle文件中添加依赖:
dependencies {
......
def paging_version = "2.1.2"
// kotlin使用 paging-runtime-ktx(Java使用 paging-runtime)
implementation "androidx.paging:paging-runtime-ktx:$paging_version"
// 或者-没有Android依赖项进行测试(Java使用 paging-common)
testImplementation "androidx.paging:paging-common-ktx:$paging_version"
// 可选-RxJava支持(Java使用 paging-rxjava2)
implementation "androidx.paging:paging-rxjava2-ktx:$paging_version"
//RecyclerView列表
implementation 'androidx.recyclerview:recyclerview:1.1.0'
//SwipeRefreshLayout刷新控件
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
//DataBinding数据绑定(没有用到可不添加)
kapt "com.android.databinding:compiler:$gradle_version"
}
Paging的3个主要组件:
- PagedList:可观察的分页列表,通常在ViewModel中创建PagedList对象,以及配置分页属性PagedList.Config
- DataSource:数据源,可继承的数据源有三种
PageKeyedDataSource:按页加载,如请求数据时传入page页码
ItemKeyedDataSource:按条目加载,即请求数据需要传入其它item的信 息,如加载第n+1项的数据需传入第n项的id
PositionalDataSource:按位置加载,如加载指定从第n条到n+20条
- Factory:数据工厂,需实现create()方法,返回一个DataSource对象
数据类:
data class User(
val name: String,
val age: Int,
val index: Int = 0
) {
override fun toString(): String {
return "User(name='$name', age=$age, index=$index)"
}
}
数据存储类
class UserViewModel : ViewModel() {
private var users: LiveData<PagedList<User>>
init {
//初始化数据工厂
val factory = UserDataSourceFactory()
//初始化分页配置
val config = PagedList.Config.Builder().apply {
setPageSize(20) //每页显示条目数量
setInitialLoadSizeHint(20) //首次加载条目数量 默认为 pageSize * 3
setEnablePlaceholders(false)//当item为null是否使用PlaceHolder展示
setPrefetchDistance(1) //距离底部多少条数据开始预加载,设置0则表示滑到底部才加载
}.build()
users = LivePagedListBuilder<Int, User>(factory, config).build()
}
//获取数据
fun getUsers(): LiveData<PagedList<User>> = users
}
DataSource 数据源(三选一)
PositionalDataSource数据源
//按位置加载,如加载指定从第n条到n+20条
class UserPosDataSource : PositionalDataSource<User>() {
//初次加载
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<User>) {
val result = setData(0, params.pageSize)
callback.onResult(result, 0)
}
//分页加载
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<User>) {
val result = setData(params.startPosition, params.loadSize)
callback.onResult(result)
}
//模拟数据
private fun setData(start: Int, size: Int): List<User> {
val users = mutableListOf<User>()
for (i in start until start + size) {
users.add(User("张三$i", 20))
}
return users
}
}
ItemKeyedDataSource数据源
//按条目加载,即请求数据需要传入其它item的信息,如加载第n+1项的数据需传入第n项的id
class UserItemDataSource : ItemKeyedDataSource<Int, User>() {
//初次加载
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<User>) {
val result = setData(0)
callback.onResult(result, 0, 20)
}
//滑到底部加载数据
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<User>) {
val result = setData(params.key)
callback.onResult(result)
}
//滑倒顶部加载数据
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<User>) {
val result = setData(params.key)
callback.onResult(result)
}
//获取key
override fun getKey(item: User): Int {
return item.index
}
//模拟数据
private fun setData(key: Int): List<User> {
val users = mutableListOf<User>()
for (i in key + 1..(key + 1) + 10) {
users.add(User("张三$i", 20, i))
}
return users
}
}
PageKeyedDataSource数据源
//按页加载,如请求数据时传入page页码
class UserPageDataSource : PageKeyedDataSource<Int, User>() {
//初次加载
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, User>) {
val result = setData(0)
callback.onResult(result, 0, 1)
}
//加载下一页
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, User>) {
val result = setData(params.key)
callback.onResult(result, params.key + 1)
}
//加载上一页
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, User>) {
val result = setData(params.key)
callback.onResult(result, params.key - 1)
}
//模拟数据
private fun setData(page: Int): List<User> {
val users = mutableListOf<User>()
for (i in page * 10 + 1..(page + 1) * 10) {
users.add(User("张三$i", 20))
}
return users
}
}
Factory 数据工厂
class UserDataSourceFactory : DataSource.Factory<Int, User>() {
override fun create(): DataSource<Int, User> {
return UserPosDataSource()
//return UserPageDataSource()
//return UserItemDataSource()
}
}
Adapter 列表适配器
class UserAdapter() : PagedListAdapter<User, UserAdapter.ViewHolder>(DIFF_CALLBACK) {
companion object {
//对数据源返回的数据进行了比较处理,
//它的意义是——我需要知道怎么样的比较,
//才意味着数据源的变化,并根据变化再进行的UI刷新操作
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.name == newItem.name
}
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.item_user_list,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//绑定数据
holder.dataBinding.setVariable(BR.user, getItem(position))
}
inner class ViewHolder(var dataBinding: ViewDataBinding) :
RecyclerView.ViewHolder(dataBinding.root)
}
Activity
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: UserViewModel
private var adapter: UserAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//初始化视图
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
//绑定监听
binding.myHandles = MyHandles()
//初始化viewModel
viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(UserViewModel::class.java)
//初始化列表
binding.rvView.layoutManager = LinearLayoutManager(this)
adapter = UserAdapter()
binding.rvView.adapter = adapter
//通过viewModel拿到数据并提交数据
viewModel.getUsers().observe(this, Observer {
adapter!!.submitList(it)
})
//下拉刷新
binding.srlLayout.setOnRefreshListener {
srl_layout.isRefreshing = false
viewModel.getUsers().value?.dataSource?.invalidate()
}
}
inner class MyHandles{
//主动点击刷新
fun refresh(view: View) {
adapter!!.submitList(null)
viewModel.getUsers().value?.dataSource?.invalidate()
}
}
}
注意:如果使用的是PositionalDataSource数据源,主动刷新时需将数据列表置空,如:adapter!!.submitList(null),否则刷新数据,界面无法回到最顶部
显示:
本文地址:https://blog.csdn.net/summerrse/article/details/107542561