簡體   English   中英

從數據庫+網絡加載數據(Room + Retrofit + RxJava2)

[英]Loading data from Database + Network (Room + Retrofit + RxJava2)

我有一個示例API請求,它返回用戶監視列表的列表。 我想在用戶加載監視列表屏幕時實現以下流程

  1. 立即從DB緩存加載數據。( cacheWatchList

  2. 在后台啟動RetroFit網絡呼叫。

    一世。 onSuccess返回apiWatchList
    II。 onError返回cacheWatchList

  3. Diff cacheWatchList vs apiWatchList

    一世。 相同 - >一切都很好,因為數據已經顯示給用戶什么都不做。

    II。 不同 - >將apiWatchList保存到本地存儲並將apiWatchList發送到下游。

到目前為止我做了什么?

Watchlist.kt

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

LocalStore.kt (Android室)

  fun saveUserWatchlist(repositories: List<Repository>): Completable {    
    return Completable.fromCallable {      
      watchlistDao.saveAllUserWatchlist(*repositories.toTypedArray())
    }
  }

RemoteStore.kt (改造api調用)

  fun getWatchlist(userId: UUID): Single<Watchlist?> {
    return api.getWatchlist(userId)
  }

DataManager.kt

  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)
  }

上述流程的問題在於,即使兩個數據都相同,它onNext為每個流源調用onNext 兩次到下游(演示者)。

我可以在演示者中執行數據差異邏輯並相應地更新,但我希望DataManager類為我處理邏輯(CleanArchitecture,SOC)。

我的問題?

  1. 實現上述邏輯的最佳方法是什么?

  2. 我是否泄漏了DataManager中的內部訂閱(參見: doOnSuccess代碼)? 當演示者被銷毀時,我正在處理外部訂閱。

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. 由於內部observable有多個發射(來自remoteSource的更新數據,來自本地和新數據的初始數據)將Single轉換為Observable。
  4. 將來自remoteSource的數據與來自localStore的數據進行比較,並僅在newData!= localData的情況下繼續數據。
  5. 對於過濾器啟動localSource以保存數據后的每次發射,並在完成此操作后,將保存的數據保存為Single。
  6. 根據要求,在遠程請求開始時,應該繼續執行來自localStore的數據,並且只需在運營商鏈的末尾添加startWith即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM