Android Jetpack 之 Paging3的一些踩坑记录(1),2024年最新android自带小游戏

}

.filterNotNull()

.mapLatest { generation ->

PagingData(generation.pageEventFlow, PagerUiReceiver(generation, retryChannel))

}

.collect { send(it) }

}

可以看到在 flow 先是创建了分页快照,最后通过该对象的 pageEventFlow 和 一个 PagerUiReceiver 实例来创建了 PagingData 并发送出来供外部使用。此时可以再看 PageFetcherSnapshot 的 pageEventFlow,说实话里面太多协程内容,并看不太懂,但是能清楚 PagingSource 的 load 方法是在里面执行。

综合上面的线索,PagingData 能够通过触发刷新来提供,而刷新通过调用 PagingDataAdapter 的 refresh 方法,然后层层深入,最终通过 PagerUiReceiver 对象的 refresh 方法 调用 refreshChannel.offer(true)来触发(又是协程的东西…)。

接下来是页码的处理。在 PageFetcherSnapshot 的 pageEventFlow 中可以发现在触发刷新的时候会通过以下方法构建 LoadParams 并调用 PagingSource 的 load 方法加载数据。

//部分参数就是当初配置PagingConfig的数据,包括key也是构建Pager时传入的initialKey(默认值null)

private fun loadParams(loadType: LoadType, key: Key?) = LoadParams.create(

loadType = loadType,

key = key,

loadSize = if (loadType == REFRESH) config.initialLoadSize else config.pageSize,

placeholdersEnabled = config.enablePlaceholders,

pageSize = config.pageSize

)

也就是说需要跳页的时候只要触发刷新,然后在 PagingSource 的 load 方法中加载数据的时候使用个人期望的页码,而不是使用通过LoadParams带过来的初始页面的页码即可。

也就是说需要跳页的时候只要触发刷新,然后在 PagingSource 的 load 方法中加载数据的时候使用个人期望的页码,而不是使用通过LoadParams带过来的初始页面的页码即可。

坑点二、在界面不可见后一段时间切回来时会重新加载数据。

这点算不算是坑不知道,但是影响了APP的使用体验(因为监听了加载状态,所以每次切换回来的时候都会出现加载圈),所以必须排查一下。

首先想到的是不是因为 PageFetcher 的 refresh 方法被调用了。观察调用掉一个是 PagerUiReceiver 对象,专门提供给adapter那边的方法的。遂从 PageFetcherSnapshot 的调用点入手,经过几次调试发现整个刷新行为是因为PageFetcher的flow被重新构建,在继续往外扒最终发现是LiveData搞的鬼。但个人印象中哪怕页面出现切换,LiveData中的数据不发生变化的话也不会出现发送数据的情况。

有一点值得让人注意的是Paging3提供的对象是协程中的flow,最后是通过 asLiveData 方法转到 LiveData对象。

@JvmOverloads

fun Flow.asLiveData(

context: CoroutineContext = EmptyCoroutineContext,

timeoutInMs: Long = DEFAULT_TIMEOUT

): LiveData = liveData(context, timeoutInMs) {

collect {

emit(it)

}

}

看到了一个很有意思的参数 timeoutInMs,默认值刚好是界面不可见的时间,而后面最终提供了一个CoroutineLiveData对象,此时真相大白。

还是因为对协程不熟悉的原因,大致了解了一下CoroutineLiveData这个对象。大致就是协程在界面不可见之后不会立即取消,会先等待 timeoutInMs 的时间再去检查界面是否可见,如果此时还不可见就取消协程。

综上个人推断产生这个问题的原因是Paging3内部拥有一个阻塞协程,通过 PageFetcher 中的 refreshChannel 和 retryChannel 来中止阻塞执行请求数据,在界面切换不可见之后,CoroutineLiveData会取消这个协程,在界面返回后又会重建一个协程导致触发刷新。

解决方法:

  1. 对PagingFlow添加cacheIn(viewModelScope)。

  2. 不使用CoroutineLiveData,直接用 lifecycleScope.launchWhenCreated 和 flow 来接收 PagingData 数据。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

面试复习笔记:

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
限于阅读各大系统源码,还包括各种优秀的开源库。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-EnTHLXj5-1712684015416)]

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值