2017-03-09 5 views
3

次のコードは、ファイルのダウンロードを表しています。 Observableが破棄されると、そのコールはキャンセルされます。私の場合、ObservableはFragmentのonDestroy()メソッドに置かれます(実際には破棄されている、または破棄されるフラグメント上でファイルをダウンロードする必要はないためです)。ファイルのダウンロードプロセス中にキャンセルのシナリオが発生するたびに、このコードはSocketExceptionでクラッシュします。メッセージは、「ソケットクローズ」または「ソケット以外のソケット操作」のいずれかです。私の質問は、OkHttpを使って進行中のダウンロードリクエストを適切にキャンセルする方法です。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(); 
      } 
     } 
    }); 
} 

コンソール:あなたが破壊された断片化しながら、すでに退会している人からエミッタへonError()を送信しているコード

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

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

表示されているコードは、rx-javaやrx-androidとは関係ありません。 –

+0

Util.closeQuietly()メソッドのコードを添付できますか? – yosriz

+0

これは設計通りに機能しています。コールをキャンセルすると、ストリームから例外がスローされます。 –

答えて

0

。 チェックしてください:

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