欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Jetpack Paging3分页库

程序员文章站 2022-03-11 15:02:50
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分页库

简介
分页库可帮助您一次加载和显示一小块数据。按需载入部分数据会减少网络带宽和系统资源的使用量。
Jetpack Paging3分页库

依赖
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),否则刷新数据,界面无法回到最顶部

显示:
Jetpack Paging3分页库

本文地址:https://blog.csdn.net/summerrse/article/details/107542561