Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava 2 / Retrofit 2 - NetworkOnMainThreadException

I need to perform a request, if my token is expired I need to refresh it and retry the request.

This is how I'm trying to do it, at the moment I can refresh the token but it throws me a NetworkOnMainThreadException. It finishes the request,update the token and reaches logs, but that exception its killing me. How can I avoid that?

    public Observable<Estabelecimento> listarEstabelecimentos() {
    return Observable.defer(this::getListarEstabelecimentoObservable)
            .retryWhen(throwableObservable -> throwableObservable.flatMap(
                    throwable -> {
                        if (throwable instanceof UnauthorizedException) {
                            return mRequestManager.getTokenObservable(AutoAtendimentoApplication.getContext())
                                    .doOnNext(response -> /* log stuff */)
                                    .flatMap((Function<AuthResponse, ObservableSource<?>>) response2 ->
                                            getListarEstabelecimentoObservable()
                                                    .doOnNext(estabelecimento ->
                                                            /* log stuff */)
                                                    )
                                    );
                        }
                        return Observable.error(throwable);
                    }));
}

NetWorkErrorHandler:

    public <T> T  processError(Response<T> response ) {
    switch (response.code()) {
        case 401:
            throw new UnauthorizedException();
        default:
            return response.body();
    }
}

Token:

       private Observable<AuthResponse> getToken(Context context,
                                          @GrantType.GrantTypeDef String grantType, @Nullable String refreshToken) {

    SessionManager sessionManager = SessionManager.getInstance(context);
    Usuario usuario = sessionManager.getUser();

    AuthRequest request = new AuthRequest(usuario.getUsername(),
            usuario.getPassword(), grantType, refreshToken);

    return mAuthAPIService.getToken(request)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .map(response -> storeTokens(response, context));
}

Edit 1: I'm pretty sure the problem happens inside the flatmap and put subscribeOn does not solve the problem

Edit 2: Code update

like image 634
Felipe Castilhos Avatar asked May 16 '17 17:05

Felipe Castilhos


1 Answers

Your network is running on main thread, you can solve it by adding observeOn(AndroidSchedulers.mainThread()) and subscribeOn(Schedulers.io()) to your observable.

The observeOn(...) means that the results are emmited on the specified thread - in this case the UI thread.

The subscribeOn(...) call is basically where the request is processed. If omitted the computation is done on current thread.

like image 128
user_4685247 Avatar answered Sep 25 '22 11:09

user_4685247