分页3初始加载未显示

问题描述

我正在使用分页3,除了初始加载状态之外,其他所有东西都可以正常工作。我正在添加withLoadStateFooter,但它在第一次调用时从未显示加载状态

这是我的实现方式

加载状态适配器

class LoadStateAdapter (
    private val retry: () -> Unit
): LoadStateAdapter<LoadStateViewHolder>() {

    override fun onBindViewHolder(holder: LoadStateViewHolder,loadState: LoadState) {
        holder.bindTo(loadState)
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,loadState: LoadState
    ): LoadStateViewHolder {
        return LoadStateViewHolder.create(parent,retry)
    }
}

加载状态视图持有人

class LoadStateViewHolder(
    view : View,private val retryCallback: () -> Unit
) : RecyclerView.ViewHolder(view) {

    private val progressBar = view.findViewById<ProgressBar>(R.id.progress_bar)
    private val errorMsg = view.findViewById<TextView>(R.id.error_msg)
    private val btnRetry = view.findViewById<Button>(R.id.retry_button)
        .also {
            it.setOnClickListener { retryCallback() }
        }
    private var loadState : LoadState? = null

    companion object {
        fun create(parent: ViewGroup,retryCallback: () -> Unit): LoadStateViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.network_state_item,parent,false)
            return LoadStateViewHolder(
                view,retryCallback
            )
        }
    }


    fun bindTo(loadState: LoadState) {
        this.loadState = loadState

        btnRetry.isVisible = loadState !is LoadState.Loading
        errorMsg.isVisible = loadState !is LoadState.Loading
        progressBar.isVisible = loadState is LoadState.Loading

        if (loadState is LoadState.Error){
            errorMsg.text = loadState.error.localizedMessage
        }
    }
}

分页来源

override suspend fun load(params: LoadParams<Int>): LoadResult<Int,Model> {

    try {
        // Load page 1 if undefined.
        val currentPage = params.key ?: 0
        val offset = currentPage * 50

        val requestParams = hashMapOf<String,Any>()
        requestParams.put("limit",50)
        requestParams.put("offset",offset)

        val response =  repository.getList(requestParams)
        val isFinish = response.paging != null && response.paging!!.next == null

        return LoadResult.Page(
            data = response.data ?: mutableListOf(),prevKey = null,// Only paging forward.
            nextKey = if (isFinish) null else currentPage + 1
        )
    } catch (e: Exception) {
        // Handle errors in this block
        return LoadResult.Error(e)
    }
}

查看模型

val listPagingFlow = Pager(PagingConfig(pageSize = 50)) {
    MyPagingSource(repository)
}.flow.cachedIn(viewModelScope)

活动

    val pagingAdapter = MyPagingAdapter()
    list.apply {
        setHasFixedSize(true)
        adapter = pagingAdapter.withLoadStateFooter(
            footer = LoadStateAdapter { pagingAdapter.retry() }
        )
    }

    lifecycleScope.launch(Dispatchers.IO) {
        viewModel.listPagingFlow.collectLatest { pagingData ->
            pagingAdapter.submitData(pagingData)
        }
    }

MyPagingAdapter 很简单PagingDataAdapter

简而言之;加载状态正常,但在第一次请求时未显示。可以帮忙吗?

当前版本3.0.0-alpha04

解决方法

withLoadStateFooter返回一个ConcatAdapter,它将原始PagingDataAdapter的结果与一个LoadStateAdapter侦听CombinedLoadState.append事件的结果连接起来。因此,我们不希望它在初始加载期间返回一个项目(loadType == REFRESH),并且采用这种方式进行设计,因为在加载任何项目之前显示“页脚”没有任何意义。

但是,要实现您想要的目标,您只需创建自己的ConcatAdapter即可,它非常紧密地反映了.withLoadStateFooter的实现:

val originalAdapter = MyPagingDataAdapter(...)
val footerLoadStateAdapter = MyFooterLoadStateAdapter(...)

addLoadStateListener { loadStates ->
    // You need to implement some logic here to update LoadStateAdapter.loadState
    // based on however you want to prioritize between REFRESH / APPEND load states.
    // Something really basic might be:
    // footerLoadStateAdapter.loadState = when {
    //     loadStates.refresh is NotLoading -> loadStates.append
    //     else -> loadStates.refresh
    // }
    footerLoadStateAdapter.loadState = ...
}
return ConcatAdapter(originalAdapter,footerLoadStateAdapter)
,

使用页脚 LoadStateAdapter 显示初始加载会导致问题。该列表将自动滚动到评论中提到的底部。

解决这个问题的方法是使用两个 LoadStateAdapter,一个显示初始加载,第二个显示加载更多项目时的加载。

fun <T : Any,V : RecyclerView.ViewHolder> PagingDataAdapter<T,V>.withLoadStateAdapters(
    header: LoadStateAdapter<*>,footer: LoadStateAdapter<*>
): ConcatAdapter {
    addLoadStateListener { loadStates ->
        header.loadState = loadStates.refresh
        footer.loadState = loadStates.append
    }

    return ConcatAdapter(header,this,footer)
}
,

作为@dlam的答案,您可以在适配器中使用自定义ConcatAdapter而不是withLoadStateFooter

fun withMySpecificFooter(
    footer: LoadStateAdapter<*>
): ConcatAdapter {
    addLoadStateListener { loadStates ->
        footer.loadState = when (loadStates.refresh) {
            is LoadState.NotLoading -> loadStates.append
            else -> loadStates.refresh
        }
    }
    return ConcatAdapter(this,footer)
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...