【问题标题】:How to handle multiple data sources with rxjava?如何使用 rxjava 处理多个数据源?
【发布时间】:2016-06-01 13:18:39
【问题描述】:

是这样的:

我有领域层为业务逻辑提供数据获取接口,我有2个数据源:本地数据库和远程网络。

它是这样工作的:

  1. 请求所有用户:DataRepository.getInstance().getUsers();
  2. 在 DataRepository 中,有 2 个来源:
    • LocalDataSource.getUsers() 从本地数据库中获取所有用户,如果没有数据则忽略此请求。
    • RemoteDataSource.getUsers() 从我们的服务器请求最新的用户列表(即使本地数据库中有数据,为了保持数据更新),当请求数据时,将其保存或更新到本地数据库并发送回结果。

我知道我可以通过在DataRepository 中这样做来实现我的目标:

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

现在想想我已经在项目中使用了 rxjava,为什么不使用 SqlBrite 和 Retrofit2 RxAdapters 来做这件事更方便呢? 所以LocalDataSource.getUsers() 现在返回Observable&lt;List&lt;User&gt;&gt;,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); // ???
}

【问题讨论】:

    标签: rx-java retrofit2 rx-android sqlbrite


    【解决方案1】:

    我应该在 DataRepository.getUsers() 中做什么才能实现与旧技巧相同的效果?

    在这种情况下,您可以使用concat:

    public Observable<List<User>> getUsers() {
        return Observable.concat(localUsers.first(), remoteUsers);
    }
    

    但是如果不管是先本地还是先远程结果,你可以使用merge:

    public Observable<List<User>> getUsers() {
        return Observable.merge(localUsers.first(), remoteUsers);
    }
    

    另外,如果你只想要一个结果(快一胜),你可以使用amb:

    public Observable<List<User>> getUsers() {
        return Observable.amb(localUsers.first(), remoteUsers);
    }
    

    【讨论】:

    • 重复的用户对象会自动消除吗?例如,两种情况下都存在User1,输出流中只有一个User1?
    • @IlanthirayanParamanathan 不,它不会,concat 和 merge 不会为您执行重复数据删除工作。
    • 我找到了使用 distinct() 消除重复的方法,为了在 User Model 类中实现必须重写 hasCode()、equal(Object obj) 方法。 Observable.concat(localUsers.first(), remoteUsers) .distinct(new Func1 &lt;User, Integer&gt;){ @Override public Integer call (User user){ return user.getId(); } }
    • 是的,你可以做到。
    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2017-09-26
    相关资源
    最近更新 更多