2017-03-09 3 views
3

다음 코드는 파일 다운로드를 나타냅니다. Observable이 처리되면 호출이 취소됩니다. 필자의 경우 Observable은 Fragment의 onDestroy() 메소드에서 처리됩니다 (사실상 파편에 파 일을 다운로드 할 필요가 없기 때문에 Observable은 파기됩니다). 파일의 다운로드 과정에서 취소가 발생할 때마다이 코드는 SocketException과 충돌합니다. 메시지는 "Socket Closed"또는 "Non-socket on Socket operation"일 수 있습니다. 내 질문은 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(); 
      } 
     } 
    }); 
} 

콘솔 : 코드에서

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-안드로이드와 아무 상관이없는 표시된 코드입니다. –

+0

Util.closeQuietly() 메서드의 코드를 첨부 할 수 있습니까? – yosriz

+0

그것은 설계된대로 작동합니다. 통화를 취소하면 스트림에서 예외가 발생합니다. –

답변

0

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

당신이 파괴 된 생태계 동안 이미 탈퇴 누구 에미 터 onError()을 보내고있다. 확인 마십시오 :

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