Android:使用Rx android和Retrofit时出现NetworkOnMainThreadException错误。
Android:使用Rx android和Retrofit时出现NetworkOnMainThreadException错误。
当使用rx android和retrofit时,我遇到了网络线程异常。这是我的代码:\n
public ObservablerequestApiItem() { return getauthenticationtoken.getToken().flatMap(new Func1 >() { public Observable call(String token) { return service.postdata(value1, value2, value3, token); } }).subscribeOn(Schedulers.io()); } public void postdata() { requestApiItem() .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber () { @Override public void onCompleted() { System.out.print("Complete"); } @Override public void onError(Throwable e) { System.out.print("Fail"); } @Override public void onNext(PostVariablesModel apiResult) { System.out.print(apiResult.toString()); } }); }
\n在完成http调用后,我们需要取消订阅吗?有什么想法吗?\n异常如下所示。我在代码中的postdata方法的onError方法中遇到了这个异常:\n
android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273) at java.net.InetAddress.lookupHostByName(InetAddress.java:431) at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252) at java.net.InetAddress.getAllByName(InetAddress.java:215) at okhttp3.Dns$1.lookup(Dns.java:39) at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:170) at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:136) at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:81) at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:171) at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121) at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179) at okhttp3.RealCall.execute(RealCall.java:63) at retrofit2.OkHttpCall.execute(OkHttpCall.java:174) at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171) at rx.Subscriber.setProducer(Subscriber.java:211) at rx.Subscriber.setProducer(Subscriber.java:205) at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152) at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138) at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50) at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) at rx.Observable.unsafeSubscribe(Observable.java:8666) at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:250) at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:147) at rx.internal.operators.OperatorMap$MapSubscriber.onNext(OperatorMap.java:74) at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:227) at rx.android.schedulers.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7231) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
问题出现的原因是在postdata()方法中,requestApiItem()方法没有在后台线程中执行,而是在主线程中执行,导致了NetworkOnMainThreadException异常。
解决方法是将requestApiItem()方法放在后台线程中执行。可以使用RxAndroid和Retrofit的线程调度功能来实现。具体的解决方法是在postdata()方法中,使用observeOn()方法指定观察者在主线程中执行,使用subscribeOn()方法指定被观察者在后台线程中执行。代码如下:
public void postdata() { requestApiItem() .observeOn(AndroidSchedulers.mainThread()) // 指定观察者在主线程中执行 .subscribeOn(Schedulers.io()) // 指定被观察者在后台线程中执行 .subscribe(new Subscriber<PostVariablesModel>() { public void onCompleted() { System.out.print("Complete"); } public void onError(Throwable e) { System.out.print("Fail"); } public void onNext(PostVariablesModel apiResult) { System.out.print(apiResult.toString()); } }); }
另外,也可以尝试使用上面编辑中给出的解决方法,将requestApiItem()方法中的flatMap()方法替换为简单地使用Observable.just()方法返回结果。具体代码如下:
public Observable<PostVariablesModel> requestApiItem() { return service.postdata(value1, value2, value3, token) .flatMap(new Func1<PostVariablesModel>() { public Observable<? extends PostVariablesModel> call(PostVariablesModel yourModel) { return Observable.just(yourModel); } }); }
以上是解决Android中使用RxAndroid和Retrofit时出现NetworkOnMainThreadException异常的原因和解决方法。
Android : NetworkOnMainThreadException using Rx android and Retrofit
在使用RxAndroid和Retrofit时出现了NetworkOnMainThreadException异常。根据问题相关的讨论,从代码中可以看到以下几点:
1. 在getauthenticationtoken.getToken()方法中,使用了.subscribeOn(Schedulers.io())指定了线程为io线程。
2. 在Retrofit的Builder中,使用了RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())指定了调度器为io线程。
然而,尽管已经进行了正确的修正,仍然出现了相同的错误。在问题讨论中提到,没有在log cat中看到任何错误,应用程序也没有因此而崩溃。
根据回答中提供的链接,可以看到在UI线程上允许网络请求并不是解决问题的方法。此外,还提供了一个示例代码,但是这并不是一个好的解决方法。
通过进一步探讨,发现问题出现在某个Retrofit API端点上,忘记了在其中指定subscribeOn(Schedulers.io())。如果将其设置为Retrofit请求的默认调度器,则不需要在每个请求中手动指定subscribeOn(Schedulers.io()),因为它们将默认在后台线程上运行。
问题的原因是在某个Retrofit API端点上忘记了指定subscribeOn(Schedulers.io()),解决方法是在相关的API端点中添加subscribeOn(Schedulers.io()),或者将其设置为Retrofit请求的默认调度器。