Skip to content

尾部加载更多(向下加载更多)

mumu edited this page Aug 26, 2022 · 1 revision

尾部加载更多(或称为“向下加载更多”)

关键类 TrailingLoadStateAdapter,继承自 LoadStateAdapter

基础使用

使用默认的“加载更多”布局,实现“加载更多”的功能

  • 创建所需对象
    // 第一步,创建 adapter
    val mAdapter = RecyclerViewAdapter()
    
    
    // 第二部,使用 Builder 创建 QuickAdapterHelper 对象,这里需要传入你的 mAdapter
    val helper = QuickAdapterHelper.Builder(mAdapter)
        // 使用默认样式的尾部"加载更多"
        .setTrailingLoadStateAdapter(object : OnTrailingListener {
            override fun onLoad() {
                // 执行加载更多的操作,通常都是网络请求
                request()
            }
    
            override fun onFailRetry() {
                // 加载失败后,点击重试的操作,通常都是网络请求
                request()
            }
    
            override fun isAllowLoading(): Boolean {
                // 是否允许触发“加载更多”,通常情况下,下拉刷新的时候不允许进行加载更多
                return !viewBinding.refreshLayout.isRefreshing
            }
    }).build()
    
    /**
    * 第三步,给 RecyclerView 设置 Adapter,
    * 注意:这个adapter不是前面创建的 mAdapter,而是 helper 所提供的 adapter(ConcatAdapter)
    */
    recyclerView.adapter = helper.adapter
    
  • 设置数据及加载状态 这里直接对你创建的 mAdapter 操作数据,而不是 ConcatAdapterConcatAdapter
    if (isFirstPage) {
        // 如果是加载的第一页数据,用 submitList()
        // If it is the first page of data loaded, use submitList().
        mAdapter.submitList(list)
    } else {
        //不是第一页,则用add
        mAdapter.addAll(list)
    }
    
    if(page >= MAX_PAGE) {
        // 没有分页数据了
        /*
        Set the status to not loaded, and there is no paging data.
        设置状态为未加载,并且没有分页数据了
        */
        helper.trailingLoadState = LoadState.NotLoading(true)
        Tips.show("no more data")
    } else {
        // 后续还有分页数据
        /*
        Set the state to not loaded, and there is also paginated data
        设置状态为未加载,并且还有分页数据
        */
        helper.trailingLoadState = LoadState.NotLoading(false)
    }

自定义“加载更多”

  • 需要继承 TrailingLoadStateAdapter 实现自定义类(由于本质是一个Adapter,所以这里除了自定义布局,你还可以做更多的事情)
    class CustomLoadMoreAdapter : TrailingLoadStateAdapter<CustomLoadMoreAdapter.CustomVH>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): CustomVH {
            // 创建你自己的 UI 布局
            val viewBinding = ViewLoadMoreBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            return CustomVH(viewBinding).apply {
                viewBinding.loadMoreLoadFailView.setOnClickListener {
                    // 失败重试点击事件
                    invokeFailRetry()
                }
                viewBinding.loadMoreLoadCompleteView.setOnClickListener {
                    // 加载更多,手动点击事件
                    invokeLoadMore()
                }
            }
        }
    
        override fun onBindViewHolder(holder: CustomVH, loadState: LoadState) {
            // 根据加载状态,来自定义你的 UI 界面
            when (loadState) {
                is LoadState.NotLoading -> {
                    if (loadState.endOfPaginationReached) {
                        holder.viewBinding.loadMoreLoadCompleteView.visibility = View.GONE
                        holder.viewBinding.loadMoreLoadingView.visibility = View.GONE
                        holder.viewBinding.loadMoreLoadFailView.visibility = View.GONE
                        holder.viewBinding.loadMoreLoadEndView.visibility = View.VISIBLE
                    } else {
                        holder.viewBinding.loadMoreLoadCompleteView.visibility = View.VISIBLE
                        holder.viewBinding.loadMoreLoadingView.visibility = View.GONE
                        holder.viewBinding.loadMoreLoadFailView.visibility = View.GONE
                        holder.viewBinding.loadMoreLoadEndView.visibility = View.GONE
                    }
                }
                is LoadState.Loading -> {
                    holder.viewBinding.loadMoreLoadCompleteView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadingView.visibility = View.VISIBLE
                    holder.viewBinding.loadMoreLoadFailView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadEndView.visibility = View.GONE
                }
                is LoadState.Error -> {
                    holder.viewBinding.loadMoreLoadCompleteView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadingView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadFailView.visibility = View.VISIBLE
                    holder.viewBinding.loadMoreLoadEndView.visibility = View.GONE
                }
                is LoadState.None -> {
                    holder.viewBinding.loadMoreLoadCompleteView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadingView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadFailView.visibility = View.GONE
                    holder.viewBinding.loadMoreLoadEndView.visibility = View.GONE
                }
            }
        }
    
    
        class CustomVH(val viewBinding: ViewLoadMoreBinding) : RecyclerView.ViewHolder(viewBinding.root)
    }
  • 将自定义"加载更多"传递进去
// 实例化自定义"加载更多"的类
val loadMoreAdapter = CustomLoadMoreAdapter()
loadMoreAdapter.setOnLoadMoreListener(object : OnTrailingListener {
    override fun onLoad() {
        // 执行加载更多的操作,通常都是网络请求
    }

    override fun onFailRetry() {
        // 加载失败后,点击重试的操作,通常都是网络请求
    }

    override fun isAllowLoading(): Boolean {
        // 是否允许触发“加载更多”,通常情况下,下拉刷新的时候不允许进行加载更多
        return !viewBinding.refreshLayout.isRefreshing
    }
})

helper = QuickAdapterHelper.Builder(mAdapter)
    .setTrailingLoadStateAdapter(loadMoreAdapter) // 传递自定义的“加载跟多”
    .build()

...

功能属性说明

/**
 * Whether to display "Loading end" after all data is loaded.
 *
 * 所有数据加载完毕后,是否显示"加载结束",必须初始化时传递,中途无法修改参数。
*/
val isLoadEndDisplay: Boolean = true

/**
 * Whether to turn on autoload more.
 *
 * 是否打开自动加载更多
 */
var isAutoLoadMore = true

/**
 * Preload, the number of items from the tail.
 *
 * 预加载,距离尾部 item 的个数
 */
var preloadSize = 0

/**
 * Call this method, Check disable load more if not full page.
 * 调用此方法,当数据不满足一屏幕的时候,暂停加载更多
 */
fun checkDisableLoadMoreIfNotFullPage()