【问题标题】:RxJava Fetch from Api if cache expired如果缓存过期,RxJava 从 Api 获取
【发布时间】:2018-03-22 13:01:52
【问题描述】:

我需要从 Api 查询数据,然后将其保存到 Realm 对象。我需要从领域对象获取数据(可观察)到 Presenter,除非从最后一个 Api 查询过去 5 分钟,否则我需要再次从 Api 获取。我是 RxJava 的新手。有什么建议吗?

【问题讨论】:

    标签: android realm retrofit2 rx-java2


    【解决方案1】:

    您可以创建一个托管ReplaySubject 的类和一些更新逻辑:

    class TimedCache<T> {
        final Subject<T> cache = 
            ReplaySubject.createWithTime(5, TimeUnit.MINUTES).toSerialized();
    
        final Single<T> valueProvider;
    
        TimedCache(Single<T> valueProvider) {
            this.valueProvider = valueProvider;
        }
    
        public Observable<T> valueObservable() {
            return cache.take(1)
               .switchIfEmpty(
                   valueProvider
                   .doOnSuccess(v -> {
                       cache.onNext(v);
                       // update realm here
                   })
                   .toObservable()
               );
        }
    }
    

    【讨论】:

    • 感谢您的回复。连接到 Api 的最佳方式是什么?因为如果只是从 Api 请求中传递一个,我无论如何都需要每次都获取
    • 你的来源是什么? Retrofit 让您使用Single 定义一个 API 端点,支持 RxJava 的其他技术也是如此。
    • 我使用改造,我的意思是我如何知道何时获取 API?
    • 如果缓存为空或变旧(因此为空),它将开始从该Single 获取数据。只需开始观察valueObservable
    • 我收到“应用程序可能在其主线程上做的工作过多。”但我正在订阅 IO 线程
    【解决方案2】:

    如何设置两个不同的 observable:

    1.) 用于观察 Realm 数据:

    realm.where(MyData.class)
         .findAllAsync()
         .asFlowable()
         .filter(RealmResults::isLoaded)
         .subscribe(...);
    

    2.) 每 5 分钟获取一次数据

    Observable.interval(5, TimeUnit.MINUTES)
              .subscribeOn(Schedulers.io())
              .switchMap((ignored) -> {
                  return apiService.getData();
              })
              .subscribe((data) -> {
                  try(Realm realm = Realm.getDefaultInstance()) {
                      realm.executeTransaction((r) -> {
                          r.insertOrUpdate(data);
                      }); 
                  }
              });
    

    编辑:然后只需调用类似的方法

    flowable = realm.where(MyData.class)
         .findAllAsync()
         .asFlowable()
         .filter(RealmResults::isLoaded)
         .subscribe(...);
    
    if(cache.isOlderThanFiveMinutes()) {
        startRefreshTaskOnBackgroundThread();
    }
    

    【讨论】:

    • 在这种情况下,网络效率不高,因为用户点击按钮后才开始获取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 2017-02-13
    • 1970-01-01
    相关资源
    最近更新 更多