以下代码表示下载文件。处置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)
答案 0 :(得分:1)
代码
catch (IOException exception)
{
Log.e("Acme", "onResponse: Exception writing file:", exception);
emitter.onError(exception);
}
您正在向已经取消订阅的发射器发送onError()
。
请检查:
if (!emitter.isDisposed()) emitter.onError(exception);