IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> (Android)使用SmartRefreshLayout实现列表预加载 -> 正文阅读

[移动开发](Android)使用SmartRefreshLayout实现列表预加载

?项目需求实现让用户无感的加载更多的功能,不重复造轮子,在Github找到如下几种方案

  • SmartRefreshLayout?目前我用这个,但是只实现了demo,还没导入到项目中,后面靠测试部的同事了
  • SwipeRecyclerView?以前的项目用这个框架实现过列表项左滑删除的功能,但下拉刷新没用过。这个框架很长时间没更新了,所以没选用
  • Ultra-Pull-To-Refresh?没用过这个,而且停止维护了,所以没选
  • BaseRecyclerViewAdapterHelper?有现成的加载更多和预加载功能,但是我的adapter里面东西有点多,移过去怕少东西,就没用,这个还是蛮好用的。

因为在SmartRefreshLayout中调用autoLoadMore方法后,是会直接把footer显示在布局下面,而不是滚动到列表最后面开始,或隐藏动画加载。

自定义实现的autoLoadMoreNoSense方法对于autoloadmore修改并不多,只是把显示footer的动画操作移除,然后状态改变后,没有调用setStateLoading方法,使用的自定义的setStateLoadingNoSpinner方法。

需要注意的是在setStateLoadingNoSpinner方法中的这段:

mFooterLocked = false

?在调用setStateDirectLoading后,会将该属性设为true,锁定footer控件,然后再滚动的时候会触发嵌套滑动,将触摸事件传递到父控件去。所以在该方法执行完后要将mfooterLocked属性改回来。触发这里的嵌套滑动,有兴趣的可以去查一下“嵌套滑动”的机制。

以下代码是PreloadSmartLayout的实现。

class PreloadSmartLayout constructor(context: Context, attrs: AttributeSet?) :
    SmartRefreshLayout(context, attrs) {

    constructor(context: Context) : this(context, null)

    fun autoLoadMoreNosense(): Boolean {
        if (mState == RefreshState.None && (isEnableRefreshOrLoadMore(mEnableLoadMore) && !mFooterNoMoreData)) {
            setViceState(RefreshState.Loading)
            reboundAnimator = reboundAnimator?.run {
                duration = 0
                cancel()
                null
            }
            mKernel.setState(RefreshState.PullUpToLoad)
            if (mRefreshFooter != null) {
                if (mState != RefreshState.ReleaseToLoad) {
                    mKernel.setState(RefreshState.ReleaseToLoad)
                }
                setStateLoadingNoSpinner()
            } else {
                mKernel.setState(RefreshState.None)
            }
            return true
        } else {
            return false
        }
    }

    private fun setStateLoadingNoSpinner() {
        notifyStateChanged(RefreshState.LoadReleased)
        setStateDirectLoading(true)
        // 在调用setStateDirectLoading方法后,mFooterLocked会变为true,表示footer被锁定,
        // 此时上拉会触发嵌套滚动,滚动的是父控件而非列表,会让footer提前展示出来
        mFooterLocked = false
        val maxDragHeight: Float =
            if (mFooterMaxDragRate < 10) mFooterHeight * mFooterMaxDragRate else mFooterMaxDragRate
        if (mRefreshFooter is ClassicsFooter) {
            (mRefreshFooter as ClassicsFooter).onReleased(
                this,
                mFooterHeight,
                maxDragHeight.toInt()
            )
        }
    }

}

然后怎么使用是参考了?BaseRecyclerViewAdapterHelper中的实现,在onBindViewHolder中的position到达自己设定的预加载标志时回调事件,然后调用autoLoadMoreNoSence。如下是BRVAH中的实现

?注意:在收到adapter中预加载回调时要判断当前的加载状态,因为该回调会被调用多次。

下面是我的Fragment中的列表实现:

    private fun bindList() {
        binding.listParent.apply {
            setRefreshHeader(
                ClassicsHeader(requireContext()),
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            setRefreshFooter(
                ClassicsFooter(requireContext()),
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            setEnableAutoLoadMore(false) // 关闭列表滚动时自动触发加载更多
            setEnableOverScrollDrag(false) // 设置是否启用越界拖动(仿苹果效果)
            setEnableOverScrollBounce(false) // 是否启用越界回弹
        }.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onRefresh(refreshLayout: RefreshLayout) {
                viewModel.refreshList()
            }

            override fun onLoadMore(refreshLayout: RefreshLayout) {
                LogUtils.d("onLoadMore()")
                viewModel.loadMore()
            }
        })
        binding.recyclerList.adapter = MyAdapter(R.layout.layout_item)
            .apply {
                setOnItemClickListener { item, _ ->
                    navToDetail(item.id)
                }
                openPreload(5, object : OnPreLoadListener {
                    override fun onPreload() {
                        binding.listParent.run {
                            if (!isLoading) { // 这里需要判断加载状态,因为会被多次调用
                                autoLoadMoreNosense()
                            }
                        }
                    }
                })
            }
    }

以上功能目前只实现了demo,没有导入到正式项目中验证。如果有发现BUG请及时指出来,赠人玫瑰手有余香,互相帮助。

End

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:35:55  更:2021-12-24 18:37:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:36:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码