【问题标题】:Android rxjava with okhttp - NetworkOnMainThreadException带有 okhttp 的 Android rxjava - NetworkOnMainThreadException
【发布时间】:2017-09-15 06:24:51
【问题描述】:

我有时会遇到异常 - android.os.NetworkOnMainThreadException,有时代码可以工作。

这是我的代码

Observable.create(new Observable.OnSubscribe<Response>() {
        OkHttpClient client = new OkHttpClient();

        @Override
        public void call(Subscriber<? super Response> subscriber) {
            try {
                Response response = client.newCall(request).execute();

                subscriber.onNext(response);
                subscriber.onCompleted();
            } catch (IOException e) {
                subscriber.onError(e);
            }

        }
    }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
            .map(new Func1<Response, Res>() {
                @Override

                public Res call(Response response) {

                    String post = new Scanner(response.body().byteStream(), "UTF-8")
                            .useDelimiter("\\A").next();
                    Log.d(TAG,post);
                    return model.deCryptData(post);
                }
            })

            .subscribe(new Action1<Res>() {
                @Override
                public void call(Res res) { ...

有时结果是:

04-19 11:34:21.890 9763-9763/? W/System.err: android.os.NetworkOnMainThreadException 04-19 11:34:21.890 9763-9763/? W/System.err:在 android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273) 04-19 11:34:21.890 9763-9763/? W/System.err:在 libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249) 04-19 11:34:21.890 9763-9763/? W/System.err:在 libcore.io.IoBridge.recvfrom(IoBridge.java:549) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.net.PlainSocketImpl.read(PlainSocketImpl.java:481) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.Okio$2.read(Okio.java:138) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.AsyncTimeout$2.read(AsyncTimeout.java:238) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.RealBufferedSource.read(RealBufferedSource.java:45) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:377) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.RealBufferedSource.read(RealBufferedSource.java:45) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.RealBufferedSource.exhausted(RealBufferedSource.java:55) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.InflaterSource.refill(InflaterSource.java:101) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.InflaterSource.read(InflaterSource.java:62) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.GzipSource.read(GzipSource.java:80) 04-19 11:34:21.890 9763-9763/? W/System.err:在 okio.RealBufferedSource$1.read(RealBufferedSource.java:409) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.io.InputStreamReader.read(InputStreamReader.java:233) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.io.Reader.read(Reader.java:141) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.io.Reader.read(Reader.java:245) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.util.Scanner.readMore(Scanner.java:2068) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.util.Scanner.findDelimiterAfter(Scanner.java:2038) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.util.Scanner.setTokenRegion(Scanner.java:1953) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.util.Scanner.next(Scanner.java:965) 04-19 11:34:21.890 9763-9763/? W/System.err:在 java.util.Scanner.next(Scanner.java:941) 04-19 11:34:21.890 9763-9763/? W/System.err:在 uz.newsign.mvp.ImplPresenter$3.call(ImplPresenter.java:121) 04-19 11:34:21.891 9763-9763/? W/System.err:在 uz.newsign.mvp.ImplPresenter$3.call(ImplPresenter.java:115) 04-19 11:34:21.891 9763-9763/? W/System.err:在 rx.internal.operators.OperatorMap$MapSubscriber.onNext(OperatorMap.java:66) 04-19 11:34:21.891 9763-9763/? W/System.err:在 rx.internal.operators.OperatorUnsubscribeOn$1.onNext(OperatorUnsubscribeOn.java:53) 04-19 11:34:21.891 9763-9763/? W/System.err:在 rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:227) 04-19 11:34:21.891 9763-9763/? W/System.err:在 rx.android.scheduler.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107) 04-19 11:34:21.891 9763-9763/? W/System.err:在 android.os.Handler.handleCallback(Handler.java:739) 04-19 11:34:21.891 9763-9763/? W/System.err:在 android.os.Handler.dispatchMessage(Handler.java:95) 04-19 11:34:21.891 9763-9763/? W/System.err:在 android.os.Looper.loop(Looper.java:148) 04-19 11:34:21.891 9763-9763/? W/System.err:在 android.app.ActivityThread.main(ActivityThread.java:5441) 04-19 11:34:21.891 9763-9763/? W/System.err:在 java.lang.reflect.Method.invoke(Native Method) 04-19 11:34:21.891 9763-9763/? W/System.err:在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738) 04-19 11:34:21.891 9763-9763/? W/System.err:在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628) 04-19 11:34:21.891 9763-9763/? W/System.err:原因:rx.exceptions.OnErrorThrowable$OnNextValue:发出 onNext 值时出现 OnError:okhttp3.Response.class 04-19 11:34:21.891 9763-9763/? W/System.err:在 rx.internal.operators.OperatorMap$MapSubscriber.onNext(OperatorMap.java:70) 04-19 11:34:21.891 9763-9763/? W/System.err: ... 10 更多

我做错了什么?还是它的错误?

【问题讨论】:

    标签: android okhttp rx-android


    【解决方案1】:
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    

    订阅新线程并在 mainThread 上观察

    【讨论】:

      【解决方案2】:

      尝试自己创建线程池并订阅它。

          ExecutorService webRequestsExecutor = Executors.newFixedThreadPool(1);
          //Other stuff    
          .subscribeOn(Schedulers.from(webRequestsExecutor))
                          .observeOn(AndroidSchedulers.mainThread())
                          .unsubscribeOn(Schedulers.io())
      

      【讨论】:

        【解决方案3】:

        您不能在主线程上进行网络调用。因此对于网络,您应该使用工作线程在后台调用网络调用,并在您的工作完成后获得响应并发布您的 UI。

        【讨论】:

        • .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - 这是你的答案吗?
        【解决方案4】:

        Schedulers.io() 更改为Schedulers.newThread()

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 解决问题的附加 context 将改善答案的长度长期价值。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。提及为什么这个答案比其他答案更合适也没有什么坏处。
        【解决方案5】:
        private Call uploadImage(Callback callback){    
            OkHttpClient client = new OkHttpClient();
        
            RequestBody formBody = new FormEncodingBuilder()
                .add("param_1", "1234")
                .add("param_2", "acv")
                .build();
        
            Request request = new Request.Builder()
                .url(URL)
                .post(formBody)
                .build();
        
            Call call = client.newCall(request);
            call.enqueue(callback);
            return call;        
        }
        
        uploadImage(new Callback() {
          @Override public void onResponse(final com.squareup.okhttp.Response response)  {                                      
                    final String responseStr;                                               
                    try {
                        responseStr = response.body().string();
                        HomeActivity.this.runOnUiThread(new Runnable() {
                                   public void run() {
                                                //Update UI here                                                                
                                         }
                                    });                                                         
                        } catch (IOException e) {
                            e.printStackTrace();
                        }                                                
                     }
        @Override
        public void onFailure(Request req, IOException exp) {
            }
        });
        

        【讨论】:

          【解决方案6】:

          发生这种情况是因为您在执行实际工作的同一范围内(主线程)发出网络请求。如果网络请求是在主线程上完成的,那么您的主代码将被网络请求阻塞,直到收到响应,这将导致您的应用程序出现意外行为。在处理网络请求时,建议您在其他线程上进行网络请求。您可以通过 AsyncTask 执行此操作。 更多信息在这里:https://developer.android.com/reference/android/os/AsyncTask.html

          或者,您也可以使用 Google 的 Volley 库来处理线程问题本身。 更多信息在这里:https://developer.android.com/training/volley/index.html

          【讨论】:

          • 他正在使用 Rxjava,所以不需要异步任务或 volley
          • 谢谢。但在我使用 asynctask 之前,但现在我删除了所有旧代码,现在我正在尝试用现代 rxjava、rxandroid 和 okhttp 编写 rest api 代码,但它不能正常工作
          猜你喜欢
          • 2017-01-21
          • 2021-03-21
          • 1970-01-01
          • 2018-12-15
          • 1970-01-01
          • 1970-01-01
          • 2016-03-24
          • 2019-12-11
          • 2017-10-15
          相关资源
          最近更新 更多