美文网首页
Android 分页加载(paging)断网重连,重新加载的解决

Android 分页加载(paging)断网重连,重新加载的解决

作者: lambentlight | 来源:发表于2020-03-11 15:57 被阅读0次

    最近在使用Android官方提供的paging组件进行分页功能的时候,遇到了一个问题。首先,paging每次显示一页的数据,下滑到一定程度以后发送第二次取数据的api,以此达到分页的效果。

    当我们第一次显示成功以后,断开网络,然后划到底部。这个时候,发送API失败了。重新链接以后,再往下滑动,也不会有任何反应。这显然跟我们实际体验是有区别的。下面说一下具体的方法。

    1、基础,paging的使用。

    具体例子可以参考谷歌github上例子

    这里贴一个关于描述paging使用的文章,我觉得非常好,可以看一下,我这里不详细说了。https://juejin.im/entry/5b0d3b0251882532321468ff

    主要分三个部分
    DataSource
    PageList
    PageListAdapter

    其中,DataSource是负责处理分页。
    核心是 三个方法

    • loadInitial 初始加载数据
    • loadAfter 向后分页加载数据
    • loadBefore 向前分页加载数据

    2、 问题出现的原因

    paging在向下滑动的过程中,到达指定的位置以后,会执行loadAfter,来获取下一页的数据。但是这个处理只会执行一次,这就是为什么断网以后,重连以后,再滑动也不会有反应了。

    3、解决的思路

    通过上面的分析的原因,我们知道了原因是获取下一页的数据只会执行一次,那么我们对应的方法也就很好理解了,我们在需要的时候,再执行一次loadAfter就可以达到我们需要的效果了。

    我这边,是在recyclerview滑动到最底部的时候,重新执行loadAfter

    4、 伪代码

    DataSource

    class NoticeListDataSource(
        private val userId: String
    ) : PageKeyedDataSource<String, NoticeModel>() {
    
        // keep a function reference for the retry event
        private var retry: (() -> Any)? = null
    
        /**
         * 重新执行失败的api
         *
         */
        fun retryAllFailed() {
            val preRetry = retry
            retry = null
            preRetry?.let {
                //这里执行的时候,需要新建一个线程执行。因为一般触发这里的情况下,都在主线程
                GlobalScope.launch {
                    it.invoke()
                }
            }
        }
    
        override fun loadInitial(
            params: LoadInitialParams<String>,
            callback: LoadInitialCallback<String, NoticeModel>
        ) {
            runBlocking {
                //这里正常情况下不需要修改,因为第一页如果失败了,我们可以下拉刷新,没必要再处理
            }
        }
    
        override fun loadAfter(
            params: LoadParams<String>,
            callback: LoadCallback<String, NoticeModel>
        ) {
            runBlocking {
                //发送API
                if (Success) {
                    //API成功
                    callback.onResult(resultList, nextToken())
                    //成功以后retry置空
                    retry = null
                } else {
                    //失败了,保存当前的操作
                    retry = {
                        loadAfter(params, callback)
                    }
                }
            }
        }
    
        override fun loadBefore(
            params: LoadParams<String>,
            callback: LoadCallback<String, NoticeModel>
        ) {
            //我这边没有用到loadBefore
        }
    }
    
    

    重新执行的方法

    fun retryAllFailed() {
            _noticeListDataSourceFactory?.sourceLiveData?.value?.retryAllFailed()
    }
    

    核心部分在retry。当我们发送API失败以后,retry保存当前失败的API处理操作。我们在需要的时候,去调用retryAllFailed()方法,重新执行这次的API

    顺便一说,这里用到的是携程发送API,如果在retry的过程中,不用GlobalScope.launch的话,可能会阻塞主线程,导致卡顿。

    相关文章

      网友评论

          本文标题:Android 分页加载(paging)断网重连,重新加载的解决

          本文链接:https://www.haomeiwen.com/subject/lyycjhtx.html