これはそうである:rxjavaを使用して複数のデータソースを処理する方法は?
Iは、ビジネスロジックのためのインターフェースをフェッチデータを提供するために、ドメイン層を有していて、私は2つのデータソースを有する:ローカルデータベースおよびリモートネットワーク。 DataRepository.getInstance().getUsers();
DataRepositoryで
- 要求するすべてのユーザー:
それは次のように動作 データがない場合、ローカルデータベースからすべてのユーザーをフェッチ
LocalDataSource.getUsers()
この要求を無視します。データを保存したり、ローカルデータベースにそれを更新し、結果を送り返し、要求された、(ローカルデータベース内のデータが更新さを維持したデータの目的のために、あったとしても)当社のサーバーから最新のユーザーのリストを要求RemoteDataSource.getUsers()
。public Observable<List<User>> getUsers() { return Observable.create(new Observable.OnSubscribe<List<User>>() { @Override public void call(Subscriber<? super List<User>> subscriber) { // 1. Request users from local database List<User> localUsers = mLocalDataSource.getUsers(); if (!localUsers.isEmpty()) { subscriber.onNext(localUsers); } // 2. Request the latest user list from server // Send a retrofit2 request Call<List<User>> call = mRemoteDataSource.getUsers(); try { List<User> networkUsers = call.execute().body(); mLocalDataSource.saveUsers(networkUsers); subscriber.onNext(networkUsers); subscriber.onCompleted(); } catch (IOException e) { subscriber.onError(e); } } }); }
は、今私はすでに、なぜやってSqlBriteとRetrofit2 RxAdaptersを使用していない、プロジェクトにrxjavaを使用することを考えて:私は
DataRepository
でこれを行うことにより、私の目標を達成することができることを知っている
これはもっと便利なのですか? だから、LocalDataSource.getUsers()
は今Observable<List<User>>
を返し、そうRemoteDataSource.getUsers()
はありません。
LocalDataSource.java
public Observable<User> getUsers() {
final String sqlQuery = String.format("SELECT * FROM %s", UserTable.TABLE_NAME);
return mDatabaseHelper.createQuery(UserTable.TABLE_NAME, sqlQuery)
.mapToList(new Func1<Cursor, User>() {
@Override
public User call(Cursor c) {
return UserTable.parseCursor(c);
}
});
}
RemoteDataSource.java
public Observable<List<User>> getUsers() {
return mRetrofitApi.users();
}
質問:
私は古いトリックで行った同じことを達成するためにDataRepository.getUsers()
に何をすべきか?
public Observable<List<User>> getUsers() {
Observable<List<User>> localUsers = mLocalDataSource.getUsers();
Observable<List<User>> remoteUsers = mRemoteDataSource.getUsers()
.flatMap(new Func1<List<User>, Observable<User>>() {
@Override
public Observable<User> call(List<User> users) {
return Observable.from(users);
}
})
.doOnNext(new Action1<User>() {
@Override
public void call(User user) {
mLocalDataSource.saveUser(user);
}
})
.toList();
// What should I return to make two observables both able to emit results to the Subscriber
return Observable.concat(localUsers, remoteUsers); // ???
}
重複するユーザーオブジェクトは自動的に削除されますか?たとえば、User1は両方の場合に存在し、出力ストリームにUser1が1つだけ存在しますか? –
@IlanthirayanParamanathanいいえ、そうではありません、 'concat'と' merge'は重複除外作業を行いません。 – Piasy
私は、hasCode()、equal(Object obj)メソッドをオーバーライドする必要があるUser Modelクラスで達成するために、distinct()を使用して重複を排除する方法を発見しました。 'Observable.concat(localUsers.first()、remoteUsers) .distinct(新しい関数func1 <ユーザー、整数>){ @Overrideパブリック整数コール(ユーザユーザ){ 戻りuser.getId()。 } } ' –