0
votes

I am trying to chain two network calls in my Android app. I am using Retrofit. Basically I want to do :

  1. Make API Call to login
  2. Wait for the response of login, save the token to SharedPrefs
  3. Make another API call right after I've saved the token
  4. Wait for the response, save the data

I think I have chained the stream in the right way, the only thing is I want to update the UI in between. For example once the call starts I want to display a progressDialog ( I do that in doOnSubscribe ), or dismiss the Dialog once the call has completed ( I do that in doOnComplete ). However I get the exception Only the original thread that created a view hierarchy can touch its views. I subscribe on the io thread and observe on the mainThread so that I can make the changes to the UI, however I must be missing something.

I tried adding .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())

lower in the stream, but I still get the same error message.

 getView().onLoginAction().subscribe(aVoid -> Observable.combineLatest(
                getView().userNameObservable().map(CharSequence::toString),
                getView().passwordObservable().map(CharSequence::toString),
                Pair::new)
                .first()
                .subscribe(usernamePasswordPair -> {
                    User user = User.create(usernamePasswordPair.first, usernamePasswordPair.second, "");
                    RetrofitClientInstance.createService(AuthenticationNetworkApi.class).login(new Login(user.username(), user.password()))
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .doOnNext(loginResponse -> {
                                        AuthorizationResponse responseBody = loginResponse.body();
                                        if (responseBody != null && responseBody.getAccessToken() != null && !responseBody.getAccessToken().isEmpty()) {
                                            if (localStorage.getAccessToken().isEmpty()) {
                                                localStorage.saveAccessToken(responseBody.getAccessToken());
                                            }
                                        }
                                    }
                            ).
                            doOnSubscribe( action -> getView().showProgressDialog())
                            .doOnError(error -> {
                        getView().dismissProgressDialog();
                        getView().showErrorMessage("Login Unsuccessful");
                    }).doOnComplete(() -> getView().dismissProgressDialog()
                                    )
                            .flatMap(response -> RetrofitClientInstance.createService(ActivitiesApi.class).getUserActivities())
                             .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .doOnNext(activities -> {
                                for (UserActivityApiModel useractivity : activities
                                ) {
                                    activityService.addActivity(Activity.create(Integer.parseInt(useractivity.getId()), useractivity.getActivityName(), useractivity.getDate(),
                                            Integer.parseInt(useractivity.getValue()), Integer.parseInt(useractivity.getSubCategory().getId())));
                                }

                            }).doOnError(error -> getView().showErrorMessage(error.getMessage()))
                            .doOnComplete(() ->  getView().redirectToHomeScreen())
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe();


                }));

The error occurs here :

.doOnError(error -> {
                    getView().dismissProgressDialog();
                    getView().showErrorMessage("Login Unsuccessful");
                })
1

1 Answers

0
votes

It seems you are using a different thread to execute your backend. In that case, you can't touch the main UI thread from the second one. You need to execute first runOnUiThread { //your code }

In //your code, call the two lines of code that you put on doOnError.