使用RxJava2的房间——(Flowable,Maybe,存储库模式)

11

我在我的应用程序中使用Room作为数据库层,使用Retrofit进行网络调用 - 在Room和Retrofit中都使用了RxJava2(这是我第一个使用rxjava的项目,所以在这个领域我还是新手)。为了注入数据库、api等,我使用Dagger 2。

我想进行网络调用,并将网络响应添加到数据库中。当没有必要进行另一个网络调用时,我想从数据库中获取数据。我在我的room存储库中使用Maybe / Flowable时遇到了问题。

这是Dao:

@Dao
public interface CoinDao {
    @Query("SELECT * FROM coin")
    Flowable<List<Coin>> getAllCoins();

    @Insert
    void insert(List<Coin> coins);

    @Update
    void update(Coin... coins);

    @Delete
    void delete(Coin... coins);
}

这是我的代码库:

public class CoinRepository implements Repository {

private CoinMarketCapNetworkApi api;

private final CoinDao coinDao;


public CoinRepository(CoinMarketCapNetworkApi api, CoinDao coinDao) {
    System.out.println("Creating CoinRepository");
    this.api = api;
    this.coinDao = coinDao;
}

@Override
public Flowable<List<Coin>> getCoinResults() {
    System.out.println("getting coin results");
    return getCoinResultsFromDatabase().switchIfEmpty(getCoinResultsFromNetwork())
}


@Override
public Flowable<List<Coin>> getCoinResultsFromNetwork() {
    System.out.println("getting results from network");
    return api.getCoins().doOnNext(new Consumer<List<Coin>>() {
        @Override
        public void accept(List<Coin> coins) throws Exception {
            System.out.println("inserting to db");
            coinDao.insert(coins);
        }
    });
}

@Override
public Flowable<List<Coin>> getCoinResultsFromDatabase() {
    System.out.println("getting coins from database");
    return coinDao.getAllCoins();
}

}

我首先运行应用程序,仅通过网络调用填充数据库

@Override
public Flowable<List<Coin>> getCoinResults() {
return getCoinResultsFromNetwork();
}

当网络调用被执行时,数据成功添加到数据库中 - 我再次运行应用程序,仅从数据库获取数据,这也是成功的 - 数据从数据库中获取。

@Override
public Flowable<List<Coin>> getCoinResults() {
return getCoinResultsFromDatabase();
}

但是,当我现在尝试做这样的事情时

return getCoinResultsFromDatabase.switchIfEmpty(getCoinResultsFromMemory));

问题在于每次执行 switchIfEmpty 和 "getCoinResultsFromMemory()" 时,即使数据库中的数据可用,也会被执行。

根据https://medium.com/google-developers/room-rxjava-acb0cd4f3757中的说明,当数据库中没有数据时,Flowable将不会发出任何东西,我应该使用 Maybe。但是为什么 getResultsFromMemory() 返回空,即使数据库中有数据?在这种情况下应该如何使用 Maybe?

我已经尝试将 Flowable 更改为 Maybe。

Maybe<List<Coin>> getCoinResultsFromDatabase()

尝试做这样的事情 - 访问可能的结果并检查列表是否为空,但我不知道如何在这种情况下返回flowable:

public Flowable<List<Coin>> getCoinResults() {
getCoinResultsFromDatabase().subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<List<Coin>>() {
                @Override
                public void accept(List<Coin> coins) throws Exception {
                    System.out.println("returning coins from maybe" + coins.get(0).getId());
                    if (coins.isEmpty()) {
                        System.out.println("coin list is empty");
                        Flowable<List<Coin>> flowable = getCoinResultsFromNetwork();
                    } else {
                         Flowable<List<Coin>> flowable = getCoinResultsFromDatabase();
                    }
                }
            });
return flowable //how to access this flowable??
}
也许我漏掉了什么,有更好、更简单的解决方案。
1个回答

4

您的代码存在一些问题:

1.看起来在房间Flowable<List<Coin>> getAllCoins()中将始终返回某个值:项目列表或空列表,因此Maybe在这里无法帮助。

2.在这段代码中:

@Override
public Flowable<List<Coin>> getCoinResults() {
    System.out.println("getting coin results");
    return getCoinResultsFromDatabase().switchIfEmpty(getCoinResultsFromNetwork())
}

getCoinResultsFromNetwork方法在调用getCoinResults方法时立即调用,而不是在Flowable为空时调用(这是普通的Java方法调用)。

您需要进行延迟调用。最终解决方案可能如下所示:

@Override
public Flowable<List<Coin>> getCoinResults() {
    System.out.println("getting coin results");
    return getCoinResultsFromDatabase()
        .filter(list -> !list.isEmpty())
        .switchIfEmpty(
            Flowable.defer(() -> getCoinResultsFromNetwork()))
}

那么在这种情况下,foo().switchIfEmpty(bar())将始终执行foo和bar,而不取决于结果? - Krzysztof Palczewski
是的,因为那就像方法调用。 - Eugene Popovich
callMyMethod(getParameterFromSomewhere()) - Eugene Popovich
在您的情况下,您将始终看到“从网络获取结果”的日志输出,就像直接在方法体中一样,但只有在可观察对象为空(订阅时)时才会执行真正的网络调用。 - Eugene Popovich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接