当前位置: 首页 > 知识库问答 >
问题:

从数据库+网络加载数据(Room+Retrofit+RxJava2)

扶珂
2023-03-14

我有一个示例API请求,它返回用户的WatchList列表。我想在用户加载watchlist屏幕时实现以下流程:

差异CacheWatchListAPIWatchList

i.Same->一切都很好,因为数据已经显示给用户,什么都不做。

ii.Differs->将apiwatchlist保存到本地存储,并将apiwatchlist发送到下游。

到目前为止我做了什么?

watchlist.kt

data class Watchlist(
  val items: List<Repository> = emptyList()
)

localstore.kt(Android room)

  fun saveUserWatchlist(repositories: List<Repository>): Completable {    
    return Completable.fromCallable {      
      watchlistDao.saveAllUserWatchlist(*repositories.toTypedArray())
    }
  }
  fun getWatchlist(userId: UUID): Single<Watchlist?> {
    return api.getWatchlist(userId)
  }
  fun getWatchlist(userId: UUID): Flowable<List<Repository>?> {
    val localSource: Single<List<Repository>?> =
      localStore.getUserWatchlist()
        .subscribeOn(scheduler.computation)

    val remoteSource: Single<List<Repository>> = remoteStore.getWatchlist(userId)
      .map(Watchlist::items)
      .doOnSuccess { items: List<Repository> ->
        localStore.saveUserWatchlist(items)
          .subscribeOn(scheduler.io)
          .subscribe()
      }
      .onErrorResumeNext { throwable ->
        if (throwable is IOException) {
          return@onErrorResumeNext localStore.getUserWatchlist()
        }
        return@onErrorResumeNext Single.error(throwable)
      }
      .subscribeOn(scheduler.io)

    return Single.concat(localSource, remoteSource)
  }

>

  • 实现上述逻辑的最佳方法是什么?

    我是否泄漏了DataManager中的内部订阅(请参见:DoonSuccess代码)?。当演示者被销毁时,我将处理外部订阅。

  • 共有1个答案

    苏星宇
    2023-03-14
    fun getWatchlist(userId: UUID): Observable<List<Repository>?> {
    val remoteSource: Single<List<Repository>> = 
    remoteStore.getWatchlist(userId)
            .map(Watchlist::items)
            .subscribeOn(scheduler.io)
    
    return localStore.getUserWatchlist()
            .flatMapObservable { listFromLocal: List<Repository> ->
                remoteSource
                        .observeOn(scheduler.computation)
                        .toObservable()
                        .filter { apiWatchList: List<Repository> ->
                            apiWatchList != listFromLocal
                        }
                        .flatMapSingle { apiWatchList ->
                            localSource.saveUserWatchlist(apiWatchList)
                                    .andThen(Single.just(apiWatchList))
                        }
                        .startWith(listFromLocal)
            }
    }
    

    分步讲解:

    1. 从LocalStore加载数据
    2. 每次localStore发出数据时,使用flatMapObservable订阅remoteSource。
    3. 由于内部可观测数据(来自本地的初始数据和来自远程源的更新数据的新数据)的发射不止一个,因此将单个数据转换为可观测数据。
    4. 将来自remoteSource的数据与来自localStore的数据进行比较,并仅在newData!=localdata.
    5. 对于筛选器之后的每次发射,启动localSource以保存数据,并在完成此操作后将保存的数据作为单个数据继续。
    6. 根据请求,在远程请求开始时,应该从localStore中获取数据,只需在操作符链的末尾添加startWith就可以了。
     类似资料:
    • 除了从文件加载数据,另一个流行的数据源是互联网。 我们可以用各种各样的方式从互联网加载数据,但对我们来说,我们只是简单地读取网站的源代码,然后通过简单的拆分来分离数据。 import matplotlib.pyplot as plt import numpy as np import urllib import matplotlib.dates as mdates def graph_data(s

    • 我有一个springbatch应用程序,我将连接到一个网络数据库进行阅读。我发现的大多数示例都嵌入了数据库,用于独立测试。我不想那样做。我不确定配置是否类似。以下是我所拥有的最具德国特色的部分(带有一些异议): ,然后从应用程序启动: 我没有配置数据源。我不确定,因为我的基本上只是一个到远程网络数据库的客户端连接,它的配置是否会与我找到的各种示例的嵌入式设置不同。所以我自然会出错(如下)。我只是在

    • 问题内容: 是否可以使用Custom Spring PropertyPlaceholderConfigurer从数据库加载属性?提供给自定义PropertyPlaceholderConfigurer的数据源是否有可能在类路径中使用特定的属性文件? 我无法通过以下链接找到满意的答案? http://www.mkyong.com/spring/spring-propertyplaceholdercon

    • 所以我根据YouTube上的教程创建了一个房间数据库。我有两个栏day and likes,每个栏都有int.目前,我已经用三行数据手动填充了数据库。 下面是手动填充数据库的代码: 在我的Dao类中,我当前有Insert、Update、deleteAll和getall...方法。这里是道: } 现在,我要从Room数据库中检索基于当天的数据。所以我想要第6天的likes数,它是1。我想检索数据并将

    • 由于我已经从下面的代码中导出了数据库文件,但我无法打开导出的文件,如何打开导出的文件?

    • 是否可以用Camunda从数据库中加载BPMN XML,而不是在web应用程序中使用文件中的XML? 我们希望能够动态地添加新的工作流,而不是用定义部署新的WAR,这个想法是添加到数据库中,并通知webapp有新的定义。 谢谢,斯科特。