为何第二种代码可在map中安全发起网络请求?因数据已缓存
为什么第二种写法中在switchMap里发起网络请求是安全的?
你困惑的核心点在于plantsListSortOrderCache.getOrAwait()这个看似涉及网络的操作,放在switchMap里为什么是安全的——答案就藏在这个缓存的设计逻辑里,下面拆解两种写法的差异和缓存的作用:
先看两种写法的逻辑差异
第一种写法的问题
fun getPlantsWithGrowZone(growZone: GrowZone) = liveData { val plantsGrowZoneLiveData = plantDao.getPlantsWithGrowZoneNumber(growZone.number) // db val customSortOrder = plantsListSortOrderCache.getOrAwait() // network emitSource(plantsGrowZoneLiveData.map { plantList -> plantList.applySort(customSortOrder) }) }
- 进入
liveData块后,只会执行一次plantsListSortOrderCache.getOrAwait():如果缓存为空,发起网络请求拿排序规则;有缓存则直接用。 - 之后监听数据库数据变化时,永远用的是第一次拿到的排序规则——哪怕后续缓存里的排序规则更新了,也不会同步到结果里。
- 而且如果数据库还没返回数据,网络请求会先阻塞
liveData块,导致UI层迟迟拿不到初始数据。
第二种写法的优势
fun getPlantsWithGrowZone(growZone: GrowZone) = plantDao.getPlantsWithGrowZoneNumber(growZone.number) // db .switchMap { plantList -> liveData { val customSortOrder = plantsListSortOrderCache.getOrAwait() //network emit(plantList.applyMainSafeSort(customSortOrder)) } }
- 先监听数据库数据,每当数据库更新时,
switchMap会触发新的liveData块。 - 在新的
liveData块里调用getOrAwait():这个方法的核心逻辑是优先读取本地缓存,只有缓存不存在时才会发起网络请求。
为什么说这种写法“安全”?
- 避免重复网络请求:因为排序规则已经缓存到本地,即使数据库频繁更新,
getOrAwait()也只会读取缓存,不会每次都发起网络请求,不会浪费带宽和设备资源。 - 保证结果时效性:每次数据库数据更新时,都会取缓存里最新的排序规则处理数据,不会像第一种写法那样一直用旧规则。
- 不阻塞主线程:
liveData块运行在协程后台线程,就算真的需要发起网络请求(比如缓存过期或为空),也不会卡住UI,同时缓存机制会让这种情况极少发生。
简单来说,这里的“安全”指的是不会因为数据库的频繁变动导致不必要的网络开销,同时能保证数据处理的正确性和时效性——前提是plantsListSortOrderCache本身有完善的缓存更新机制,确保缓存内容是最新且有效的。
内容的提问来源于stack exchange,提问作者Mohammadreza Khahani
相关产品推荐
相关产品推荐

