How to combine Retrofit 2 with Realm and RxJava

2019-05-27 11:21发布

问题:

I want to save retrofit responses to realm on the background thread then pass it to the UI Thread, but its a bit tricky since Realm is very touchy with threads. so the code would look like something like this, please submit your edits to all better solutions :)

restApi.userRealmList()
        .doOnNext(userRealmModels -> {
            if (userRealmModels != null){
                mRealm = Realm.getInstance(mContext);
                mRealm.asObservable()
                        .map(realm -> mRealm.copyToRealmOrUpdate(userEntity))
                        .subscribe(new Subscriber<Object>() {
                            @Override
                            public void onCompleted() {

                            }

                            @Override
                            public void onError(Throwable e) {
                                e.printStackTrace();
                            }

                            @Override
                            public void onNext(Object o) {
                                Log.d("RealmManager", "user added!");
                            }
                        });
            }})
        .map(userEntityDataMapper::transformAll)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<List<User>>() {
             @Override
             public void onCompleted() {
                 hideViewLoading();
             }

             @Override
             public void onError(Throwable e) {
                 hideViewLoading();
                 showErrorMessage(new DefaultErrorBundle((Exception) e));
                 showViewRetry();
             }

             @Override
             public void onNext(List<User> users) {
                 showUsersCollectionInView(users);
             }
        });

回答1:

You code doesn't look like it can compile? E.g. what is userEntity. Also your copyToRealmOrUpdate isn't inside an transaction, so that will also crash, but it has nothing to do with threads.

If you want to save some data as a side-effect before sending it to the UI, you should be able to do the following:

restApi.userRealmList()
        .doOnNext(userRealmModels -> {
            if (userRealmModels != null) {
                Realm realm = Realm.getInstance(mContext);
                realm.beginTransaction();
                realm.copyToRealmOrUpdate(userRealmModels);
                realm.commitTransaction();
                realm.close();
            }})
        .map(userEntityDataMapper::transformAll)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<List<User>>() {
             @Override
             public void onCompleted() {
                 hideViewLoading();
             }

             @Override
             public void onError(Throwable e) {
                 hideViewLoading();
                 showErrorMessage(new DefaultErrorBundle((Exception) e));
                 showViewRetry();
             }

             @Override
             public void onNext(List<User> users) {
                 showUsersCollectionInView(users);
             }
        });