You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何第二种代码可在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:37:23