使用OkHttp

时间:2017-03-09 13:30:25

标签: java android okhttp

以下代码表示下载文件。处置Observable时,该呼叫将被取消。在我的例子中,Observable将被置于Fragment的onDestroy()方法中(因为它不需要继续在已经或将被销毁的片段上下载文件)。每当在文件的下载过程中取消取消时,此代码将因SocketException而崩溃。消息可以是“套接字关闭”或“非套接字上的套接字操作”。我的问题是如何使用OkHttp正确取消正在进行的下载请求?

代码:

Request request = //..
final Call call = client.newCall(request);

   call.enqueue(new Callback() {

       @Override
       public void onFailure(Call call, IOException error)
       {
          Log.e("Acme", "OnFailure:", error);
          emitter.onError(error);
       }

       @Override
       public void onResponse(Call call, Response response) throws IOException
       {
           if (response.isSuccessful())
           {
               BufferedSink sink = null;
               BufferedSource source = null;
               try
               {
                   Log.d("Acme", "onResponse: Start writing..");
                   sink = Okio.buffer(Okio.sink(file));
                   source = response.body().source();
                   sink.writeAll(source); // Crash on this line.
                   sink.flush();

                   emitter.onNext(file);
                   emitter.onComplete();
               }
               catch (IOException exception)
               {
                   Log.e("Acme", "onResponse: Exception writing file:", exception);
                   emitter.onError(exception);
               }
               finally
               {
                   Log.d("Acme", "onResponse: Trying to close..");
                   Util.closeQuietly(sink);
                   Util.closeQuietly(source);
                   Log.d("Acme", "onResponse: Closed..");
               }
           }
       }
   });

   emitter.setCancellable(new Cancellable() {

       @Override
       public void cancel() throws Exception 
       {
           if (!call.isCanceled()) 
           {
               call.cancel();
           }
       }
   });
}

控制台:

D/Acme: onResponse: Start writing..
E/AndroidRuntime: FATAL EXCEPTION: OkHttp https://acme.nl/...
Process: nl.acme.app.development.debug, PID: 12432
java.net.SocketException: Socket operation on non-socket
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:151)
    at java.net.SocketInputStream.read(SocketInputStream.java:120)
    at okio.Okio$2.read(Okio.java:138)
    at okio.AsyncTimeout$2.read(AsyncTimeout.java:236)
    at okio.RealBufferedSource.read(RealBufferedSource.java:45)
    at okhttp3.internal.http1.Http1Codec$FixedLengthSource.read(Http1Codec.java:385)
    at okio.RealBufferedSource.read(RealBufferedSource.java:45)
    at okio.RealBufferedSink.writeAll(RealBufferedSink.java:97)
    at nl.app.acme.infrastructure.network.Api$44$1.onResponse(Api.java:3322)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:135)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)

1 个答案:

答案 0 :(得分:1)

代码

catch (IOException exception)
{
    Log.e("Acme", "onResponse: Exception writing file:", exception);
    emitter.onError(exception);
}

您正在向已经取消订阅的发射器发送onError()。 请检查:

if (!emitter.isDisposed()) emitter.onError(exception);