带有okhttp的Android rxjava - NetworkOnMainThreadException

时间:2017-04-19 07:01:42

标签: android okhttp rx-android

我有时会遇到异常 - 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:at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249)   04-19 11:34:21.890 9763-9763 /? W / System.err:at libcore.io.IoBridge.recvfrom(IoBridge.java:549)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.net.PlainSocketImpl.read(PlainSocketImpl.java:481)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.net.PlainSocketImpl.access $ 000(PlainSocketImpl.java:37)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.net.PlainSocketImpl $ PlainSocketInputStream.read(PlainSocketImpl.java:237)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.Okio $ 2.read(Okio.java:138)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.AsyncTimeout $ 2.read(AsyncTimeout.java:238)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.RealBufferedSource.read(RealBufferedSource.java:45)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okhttp3.internal.http.Http1xStream $ FixedLengthSource.read(Http1xStream.java:377)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.RealBufferedSource.read(RealBufferedSource.java:45)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.RealBufferedSource.exhausted(RealBufferedSource.java:55)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.InflaterSource.refill(InflaterSource.java:101)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.InflaterSource.read(InflaterSource.java:62)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.GzipSource.read(GzipSource.java:80)   04-19 11:34:21.890 9763-9763 /? W / System.err:at okio.RealBufferedSource $ 1.read(RealBufferedSource.java:409)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.io.InputStreamReader.read(InputStreamReader.java:233)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.io.Reader.read(Reader.java:141)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.io.Reader.read(Reader.java:245)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.util.Scanner.readMore(Scanner.java:2068)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.util.Scanner.findDelimiterAfter(Scanner.java:2038)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.util.Scanner.setTokenRegion(Scanner.java:1953)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.util.Scanner.next(Scanner.java:965)   04-19 11:34:21.890 9763-9763 /? W / System.err:at java.util.Scanner.next(Scanner.java:941)   04-19 11:34:21.890 9763-9763 /? W / System.err:at uz.newsign.mvp.ImplPresenter $ 3.call(ImplPresenter.java:121)   04-19 11:34:21.891 9763-9763 /? W / System.err:at uz.newsign.mvp.ImplPresenter $ 3.call(ImplPresenter.java:115)   04-19 11:34:21.891 9763-9763 /? W / System.err:at rx.internal.operators.OperatorMap $ MapSubscriber.onNext(OperatorMap.java:66)   04-19 11:34:21.891 9763-9763 /? W / System.err:at rx.internal.operators.OperatorUnsubscribeOn $ 1.onNext(OperatorUnsubscribeOn.java:53)   04-19 11:34:21.891 9763-9763 /? W / System.err:at rx.internal.operators.OperatorObserveOn $ ObserveOnSubscriber.call(OperatorObserveOn.java:227)   04-19 11:34:21.891 9763-9763 /? W / System.err:at rx.android.schedulers.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:at java.lang.reflect.Method.invoke(Native Method)   04-19 11:34:21.891 9763-9763 /? W / System.err:at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:738)   04-19 11:34:21.891 9763-9763 /? W / System.err:at 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:at rx.internal.operators.OperatorMap $ MapSubscriber.onNext(OperatorMap.java:70)   04-19 11:34:21.891 9763-9763 /? W / System.err:... 10 more

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

6 个答案:

答案 0 :(得分:1)

.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())

订阅新主题并在mainThread上观察

答案 1 :(得分:0)

你不能在主线程上进行网络呼叫。因此,对于网络,你应该使用工作线程在后台调用网络电话,工作完成后只需获得响应并发布你的用户界面。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

尝试自己创建ThreadPool并订阅它。

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

答案 4 :(得分:0)

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) {
    }
});

答案 5 :(得分:-1)

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

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