Search code examples
rx-java2

Why am I getting NetworkOnMainThreadException?


I've tried everything and didn't get any results. I just know that subscribeOn method switches the operation to the background thread and prevent UI thread blocking and I should expect that anything happens on the background thread should not affect the user flow. Now I'm not sure that did I get the wrong info about the subscribeOn() method or do I have a bug in my code?

String profileUrl = BuildConfig.BASEURL + "pharma/patient/profile?username=" + caregiverNo;

    try {
        Observable.just(OkhttpClientManager.getInstance(APP_NAME, APP_VERSION).getRequest(profileUrl))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        callback.getDisposable(d);
                    }

                    @Override
                    public void onNext(String s) {
                        CaregiverUserResponse response = new Gson().fromJson(s, CaregiverUserResponse.class);
                        if (response.getResult().equals(Constants.API_CALL_SUCCESS)) {
                            updateCaregiverCache(response);
                            getUserData(callback, patientNo, authToken);
                        } else {
                            callback.onError(new NetworkError(new Throwable(response.getError())));
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        callback.onError(new NetworkError(e));
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    } catch (Exception e) {
        Log.e(TAG, "getCaregiverProfile: ", e);
    }

This is my code in which getRequest() function returns the response as String. and I'm getting this error NetworkOnMainThreadException and I know that subscribeOn(Schedulers.io()) performs the operation on the background thread.

Error:

android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1565)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:389)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
    at java.net.Socket.connect(Socket.java:621)
    at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:73)
    at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:246)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:166)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
    at okhttp3.RealCall.execute(RealCall.java:92)
    at com.healthapp.myadhero.network.OkhttpClientManager.getRequest(OkhttpClientManager.java:64)
    at com.healthapp.myadhero.network.Service.getCaregiverProfile(Service.java:81)
    at com.healthapp.myadhero.network.Service.access$200(Service.java:68)
    at com.healthapp.myadhero.network.Service$2.onNext(Service.java:154)
    at com.healthapp.myadhero.network.Service$2.onNext(Service.java:131)
    at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:201)
    at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:255)
    at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:124)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7682)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

Thanks in advance.


Solution

  • You are calling that getRequest before RxJava is even involved, then you hand the result value to RxJava. Using just near network call is often wrong and you should be using fromCallable.

    String profileUrl = BuildConfig.BASEURL + "pharma/patient/profile?username=" + caregiverNo;
    
    Observable.fromCallable(() -> 
        OkhttpClientManager
        .getInstance(APP_NAME, APP_VERSION)
        .getRequest(profileUrl)
    )
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<String>() {
         @Override
         public void onSubscribe(Disposable d) {
             callback.getDisposable(d);
         }
    
         @Override
         public void onNext(String s) {
             CaregiverUserResponse response = new Gson().fromJson(s, CaregiverUserResponse.class);
             if (response.getResult().equals(Constants.API_CALL_SUCCESS)) {
                 updateCaregiverCache(response);
                 getUserData(callback, patientNo, authToken);
             } else {
                 callback.onError(new NetworkError(new Throwable(response.getError())));
             }
         }
    
         @Override
         public void onError(Throwable e) {
             callback.onError(new NetworkError(e));
         }
    
         @Override
         public void onComplete() {
         }
     });