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

RxJava同时获取数据库与网络数据并缓存功能异常问题排查

问题排查
  • 逻辑不符合需求:当前代码中onErrorResumeNext仅在本地数据库查询抛出异常时才会触发网络请求,既没有实现本地、网络并行拉取数据的效果,也无法覆盖「本地数据库无匹配数据(查询返回空/Null而非执行报错)」的场景
  • 缺少数据持久化逻辑:网络请求返回的电影数据没有写入本地数据库的步骤,无法实现后续查询复用本地缓存的效果
正确实现方案

根据你的需求分为两种实现场景:

场景1:并行发起本地+网络请求,优先返回本地缓存,网络返回后更新数据

该场景下由于需要先后返回本地、网络两份数据,需将返回值从Single改为Observable:

fun loadMovie(id: Int): Observable<AboutMovie> = Observable.merge(
    // 本地查询流
    database.getMovie(id = id)
        .toObservable()
        .subscribeOn(Schedulers.io()),
    // 网络请求流,请求成功后自动存入本地库
    aboutMovieService.getMovie(movieId = id)
        .doOnSuccess { networkMovie ->
            database.insertMovie(networkMovie) // 替换为你的DAO插入方法
        }
        .toObservable()
        .subscribeOn(Schedulers.io())
)
.observeOn(AndroidSchedulers.mainThread())

场景2:优先查询本地,本地无数据/查询失败才走网络,网络数据自动存库

该场景不需要并行请求,可保留Single返回类型:

fun loadMovie(id: Int): Single<AboutMovie> = database.getMovie(id = id)
    // 本地无数据/查询出错时走网络请求
    .onErrorResumeNext { 
        aboutMovieService.getMovie(movieId = id)
            .doOnSuccess { networkMovie ->
                database.insertMovie(networkMovie)
            }
    }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
注意事项
  • 如果你使用Room实现本地数据库,查询单个不存在的记录默认会抛出EmptyResultSetException,可被onErrorResumeNext正常捕获;如果你的DAO查询无数据时返回Null,需要额外增加空判断转换为异常触发网络逻辑:
database.getMovie(id = id)
    .flatMap { movie ->
        if (movie == null) Single.error(NoSuchElementException("本地无匹配数据")) 
        else Single.just(movie)
    }
  • 上述代码已指定流运行在IO线程,插入数据库的操作不需要额外切换线程。

内容的提问来源于stack exchange,提问作者Svetl9chok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 23:54:08