Paging3 简单使用

导包

 def paging_version = "3.0.0"
	dependencies {
	    implementation "androidx.paging:paging-runtime:$paging_version"
	    // alternatively - without Android dependencies for tests
	    testImplementation "androidx.paging:paging-common:$paging_version"
	
		//数据库相关
	    implementation 'androidx.room:room-runtime:2.2.5'
	    implementation 'androidx.room:room-common:2.2.5'
	    implementation 'androidx.room:room-ktx:2.2.5'
	    kapt 'androidx.room:room-compiler:2.2.5'
    }
    //使用 "kapt" 必须导入这个
	apply plugin: 'kotlin-kapt' 
  • 本文是从数据库中读取数据显示到RecyclerView,数据库中我已提前insert了数据
    数据库相关大代码如下
@Database(entities = [User::class],version = 1,exportSchema = false)
abstract class DemoDataBase : RoomDatabase() {

    abstract val userDao:UserDao

    companion object{
        private const val DB_NAME = "demo_db"

        @Volatile
        private var instance:DemoDataBase? = null

        @Synchronized
        fun getInstance(context:Context):DemoDataBase{
            return instance?: Room.databaseBuilder(
                context,
            DemoDataBase::class.java,
            DB_NAME)
                .allowMainThreadQueries()
                .build()
                .also { instance = it }

        }
    }

}

@Entity(tableName = "tb_user")
data class User(
    @PrimaryKey
    val id:Int,
    var name:String?
)

@Dao
interface UserDao {
    @Insert
    fun insertUser(user: User)

    @Query("select * from tb_user")
    fun queryAllUser():List<User>

    @Query("select * from tb_user where id>=:start and id< :start+:size")
    fun queryPartUser(start:Int,size:Int):List<User>
}

创建PagingResource

class MyPagingResource(private val userDao: UserDao) : PagingSource<Int, User>() {


    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, User> {
        var result: LoadResult<Int, User> = LoadResult.Error(Exception("加载中..."))

        try {
            var nextPageNum = params.key ?: 1
            //从数据库读取数据 每次只获取部分内容 模拟分页获取
            val resultData = userDao.queryPartUser(nextPageNum, params.loadSize)
            result = LoadResult.Page<Int, User>(
                data = resultData ?: emptyList(),
                prevKey = if (nextPageNum == 1) null else nextPageNum - params.loadSize,
                nextKey = nextPageNum + params.loadSize
            )

        } catch (e: Exception) {
            Log.e("DEMO_TAG", "load: 加载异常")
            result = LoadResult.Error(e)
        }

        return result
    }

    override fun getRefreshKey(state: PagingState<Int, User>): Int? = null
}

上面的代码实现了按页码加载各页对象的 PagingSource。泛型中Key 类型为 Int,Value 类型为 User。key指代页码,value指代需要加载的数据类型。重写load函数,并在函数中获取数据。函数返回一个LoadResult。在获取到数据之后,调用LoadResult.Page 将数据赋给data参数,再指定好上一页和下一页的页码。另外重写了getRefreshKey方法,这个方法在更高级的用法中才会用到,这里直接返回null好了

设置 PagingData 流

fun getPagingData(): Flow<PagingData<User>> {
        val config =
            PagingConfig(
                pageSize = 10,
                prefetchDistance = 5,
                initialLoadSize = 5,
                maxSize = 10 * 3
            )
        return Pager(config = config) {
            MyPagingResource(userDao)
        }.flow
    }

定义 RecyclerView 适配器

class MyPagingAdapter : PagingDataAdapter<User, MyPagingAdapter.UserVH>(differCallback) {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = UserVH.createVH(parent)

    override fun onBindViewHolder(holder: UserVH, position: Int) {
        getItem(position)!!.let {
            holder.bind(it)
        }
    }

    companion object {
        private val differCallback = object : DiffUtil.ItemCallback<User>() {
            override fun areItemsTheSame(
                oldItem: User,
                newItem: User
            ): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(
                oldItem: User,
                newItem: User
            ): Boolean {
                return oldItem == newItem
            }
        }
    }


    class UserVH(private val binding: ItemBinding) : RecyclerView.ViewHolder(binding.root) {
        companion object {
            fun createVH(parent: ViewGroup): UserVH {
                return UserVH(
                    ItemBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                    )
                )
            }
        }

        fun bind(user: User) {
            binding.user = user
            binding.executePendingBindings()
        }
    }
}

Paging 库提供了 PagingDataAdapter 类,定义一个扩展 PagingDataAdapter 的类。
适配器还必须定义 onCreateViewHolder() 和 onBindViewHolder() 方法,并指定 DiffUtil.ItemCallback。这与定义 RecyclerView 列表 Adapter 时的通常做法相同

显示分页数据

 userDao = DemoDataBase.getInstance(this).userDao
//        repeat(100){
//            userDao.insertUser(User(it,"name__$it"))
//        }
        val rv = findViewById<RecyclerView>(R.id.rv)
        val linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.orientation = RecyclerView.VERTICAL
        rv.layoutManager = linearLayoutManager

        val myPagingAdapter = MyPagingAdapter()
        rv.adapter = myPagingAdapter
        
        lifecycleScope.launchWhenStarted {
            getPagingData().cachedIn(this).collectLatest {
                myPagingAdapter.submitData(it)
            }
        }

页脚添加下拉刷新状态

页面布局 footer_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="10dp">

        <ProgressBar
            android:id="@+id/progress_bar"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_gravity="center" />

        <TextView
            android:id="@+id/retry_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:text="Loading..." />

    </LinearLayout>
</layout>

适配器 继承自LoadStateAdapter

class MyFooterLoadStateAdapter :LoadStateAdapter<FooterViewHolder>(){
    override fun onBindViewHolder(holder: FooterViewHolder, loadState: LoadState) {
        holder.bind(loadState)
    }

    override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): FooterViewHolder {
        return FooterViewHolder(
            FooterItemBinding.inflate(LayoutInflater.from(parent.context),parent,false),
            loadState
        )
    }
}

class FooterViewHolder(
    private val binding: FooterItemBinding,
    private val loadState: LoadState
) : RecyclerView.ViewHolder(binding.root) {

    fun bind(loadState: LoadState){
        Log.e("DEMO_TAG", "bind: ----加载状态 = $loadState")
        binding.executePendingBindings()
    }

}

使加载状态生效,需要改动一下

rv.adapter = myPagingAdapter.withLoadStateFooter(MyFooterLoadStateAdapter())

添加header状态同理

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Paging3 是一个用于在 Android 应用中实现分页加载数据的开源库。它是 Google 官方发布的最新版本的 Paging 库,相较于以往的版本,Paging3 在实现简单、功能强大和性能优化方面有了很大的改进。 首先,Android Paging3 提供了强大的数据加载和显示机制。它通过将数据分割成固定大小的数据块 (page),并在需要时按需加载和展示数据,实现了无限滚动加载的效果。相较于传统的 RecyclerView 分页加载,Paging3 更加灵活,可以自动处理数据的加载和卸载,无需手动实现判断是否到底部、加载更多等繁琐逻辑。同时,Paging3 还支持局部刷新、数据源无缝替换等操作,让数据的加载和显示更加简单和高效。 其次,Paging3 在性能方面进行了优化。它使用了异步数据加载和显示机制,可以在后台线程上进行数据加载,不会阻塞主线程。同时,Paging3 采用了数据预加载和缓存策略,可以将下一页的数据提前加载到内存中,从而提高用户体验和应用的响应速度。并且,Paging3 还支持数据的持久化存储,可以将加载的数据缓存到本地数据库或文件中,避免了重复加载数据的开销。 最后,Paging3 还提供了丰富的扩展功能和灵活的定制选项。开发者可以自定义数据加载策略、数据源类型、数据显示方式等,以满足不同的业务需求。同时,Paging3 还提供了相关的辅助类和工具方法,帮助开发者更加便捷地实现数据的分页加载和显示。 总结来说,Android Paging3 是一个功能强大、性能优越的分页加载库,可以帮助开发者轻松实现数据的分页加载和显示,提高应用的用户体验和性能表现。无论是处理大量数据的列表页,还是实现无限滚动加载的功能,Paging3 都是一个值得推荐的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值