android - Observables 的 RXJava 条件执行 + 空处理

标签 android caching functional-programming reactive-programming rx-java2

我是整个函数式编程和响应式概念的新手,并试图解决以下问题。

我有一个 API 客户端,我正在为其使用 Retrofit。 还有一个本地数据库充当 API 响应的持久缓存。

我想实现的是这样的:

  1. 从本地数据库加载对象
  2. 如果没有对象或数据库返回空对象:
    • 执行 API 请求并从在线来源获取数据
    • 之后,持久化接收到的数据并返回持久化的数据
  3. 如果对象从本地数据库返回,检查是否需要在线更新
    • 需要在线更新(在线获取数据,持久化并返回持久化对象)
    • 不需要在线更新(返回本地数据)

我想出的是:

public class LocationCollectionRepository {
private final static Integer fetchInterval = 30; //Minutes
private final LocationService locationService;
private final LocalLocationCollectionRepository localRepository;

public LocationCollectionRepository(@NonNull LocationService locationService, @NonNull LocalLocationCollectionRepository localRepository) {
    this.locationService = locationService;
    this.localRepository = localRepository;
}

public Observable<LocationCollection> getLocationCollection() throws IOException {
    return localRepository.getLocationCollection()
            .takeWhile(this::shouldFetch)
            .flatMap(remoteCollection -> fetchLocationCollection())
            .takeWhile(this::isRequestSuccessful)
            .flatMap(locationCollectionResponse -> persistLocationCollection(locationCollectionResponse.body()));
}

//================================================================================
// Private methods
//================================================================================

private Observable<Response<LocationCollection>> fetchLocationCollection() throws IOException {
    return Observable.fromCallable(() -> {
        LocationServiceQueryBuilder queryBuilder = LocationServiceQueryBuilder.query();
        return queryBuilder.invoke(locationService).execute();
    });
}

private Observable<LocationCollection> persistLocationCollection(@NonNull LocationCollection locationCollection) {
    return localRepository.saveLocationCollection(locationCollection);
}

private boolean shouldFetch(@NonNull Optional<LocationCollection> locationCollection) {
    if (locationCollection.isPresent()) {
        Interval interval = new Interval(new DateTime(locationCollection.get().getTimestamp()), new DateTime());

        return locationCollection.get().getHashValue() == null || interval.toDuration().getStandardMinutes() > fetchInterval;
    } else {
        return true;
    }
}

private boolean isRequestSuccessful(Response<LocationCollection> locationCollectionResponse) throws Exception {
    if (locationCollectionResponse == null || !locationCollectionResponse.isSuccessful()) {
        throw new Exception(locationCollectionResponse.message());
    }
    return true;
}

我遇到的问题是,如果数据库返回 null,我的订阅回调中将不会返回任何对象。 我尝试了 defaultIfEmpty-Method 但得出的结论是这也无济于事,因为它需要一个对象而不是一个可观察对象。

任何想法,如何解决这个问题?

最佳答案

您可能应该使用 Flowables反而。无论如何, RxJava 2.x no longer accepts null values and will yield NullPointerException immediately or as a signal to downstream .如果你切换到 Flowables 那么你可以使用像 .onErrorReturnItem(Collections.emptyList()) 这样的东西,它在给你多少信息方面比 null 更好。没有结果,而不是可能意味着不同数量事物的 null。

关于android - Observables 的 RXJava 条件执行 + 空处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48341012/

相关文章:

Android 使用 gradle 安装 DBFlow 库

android - MvxListView 从代码中为模板布局创建绑定(bind)

caching - 在redis中,如何根据插入顺序获取键降序排列?

java - 查询 Terracotta

algorithm - Haskell中的简单链表循环检测

android - Glide 正在加载半张图像

java - SetcontentView报错InflateException

mongodb - 使用 mongodb 和 redis 的缓存失效策略

swift - 搞清楚 WWDC 2014 的 memoize - Session 404

javascript - 无法将函数传递给调用(方法)