OkHttp 학습

OkHttp
간단 한 소개
네트워크 요청 을 처리 하 는 오픈 소스 프로젝트 입 니 다. 안 드 로 이 드 의 가장 뜨 거 운 경량급 프레임 워 크 입 니 다. 모 바 일 결제 Square 회사 가 기 여 했 습 니 다.
현대 응용 프로그램 네트워크 처리 에서 HTTP 는 우리 가 데이터 와 미디어 를 교환 하 는 방식 이다.HTTP 를 효율적으로 실행 하면 데 이 터 를 더 빨리 불 러 오고 대역 폭 을 절약 할 수 있 습 니 다.
기본적으로 OKHTTP 는 효율 적 인 HTTP 클 라 이언 트 입 니 다. (1) HTTP/2 는 같은 호스트 의 모든 요청 에 소켓 을 공유 할 수 있 도록 지원 합 니 다.(2) 연결 풀 은 요청 지연 을 줄 였 습 니 다 (HTTP/2 를 사용 할 수 없 을 경우).(3) 투명 gzip 다운로드 크기 축소.(4) 응답 캐 시 는 중복 요청 네트워크 를 완전히 피한다.
네트워크 에 문제 가 생 겼 을 때 OKHTTP 는 견 뎌 냅 니 다. 일반적인 연결 문제 에서 자동 으로 복 구 됩 니 다.서비스 에 여러 개의 IP 주소 가 있 으 면 첫 번 째 연결 이 실 패 했 을 때 OKHTTP 는 예비 주 소 를 시도 합 니 다.이것 은 IPv 4 + IPv 6 와 불필요 한 데이터 센터 에 위탁 관리 하 는 서비스 에 필수 적 이다.OKHTTP 는 현대 TLS 기능 (TLS 1.3, ALPN, 인증서 고정) 을 지원 합 니 다.그것 은 광범 위 한 연결 을 실현 하기 위해 리 셋 으로 설정 할 수 있다.
OKHTTP 를 사용 하 는 것 은 매우 쉽다.그것 의 request/response API 는 유창 한 구축 자 모델 과 불변성 을 가지 도록 설계 되 었 다.그것 은 동기 화 차단 호출 과 리 턴 이 있 는 비동기 호출 을 지원 합 니 다.
OKHTTP 는 Android 5 + (API 레벨 21 +) 와 Java 8 + 를 지원 합 니 다.
 
취학 전 필수 지식
TCP 프로 토 콜 과 HTTP 프로 토 콜 을 알 아야 합 니 다.
 
홈 페이지
OkHttp
각 버 전의 차이: okhttp 3 와 이전 버 전의 okhttp 의 차이 분석
구 글 은 SDK 6.0 버 전에 서 HttpClient 클래스 를 취소 했다.
OkHttp 学习_第1张图片
 
 
OkHttp 사용 하기
구체 적 인 사용 은 다음 과 같다.https://github.com/gong-shuang/MyOkHttp이 창고 의 코드 는 두 부분 을 포함 하고, 일 부 는 서버 엔 드 코드 (자바 구현) 이 며, 다른 일 부 는 안 드 로 이 드 구현 입 니 다.
HTTP 프로 토 콜 을 이해 한 후 '요청 패키지' 를 보 내 는 것 부터 서버 '응답 패키지' 를 받 아들 이 는 과정 까지 추상적으로 추정한다.
                                                               HTTP 요청 과정
순서
추상 적
구체 적
대응 okhttp
1
가방 보 낼 대상 만 들 기
구조 체 (new)
OkHttpClient 대상 만 들 기
2
패키지 (패키지 에 데 이 터 를 채 우기)
요청 헤더 와 데 이 터 를 채 웁 니 다.
패키지 구성, 콜 대상 가 져 오기
3
보내다
발송 대기 열 에 버 리 면 전문 스 레 드 에서 발송 합 니 다.
동기 화
4
기다리다
시스템 바 텀 인터페이스 에서 응답 패 키 지 를 받 아들 이 는 대기 열 에 버 립 니 다.
5
처리 응답 패키지
응답 패 키 지 를 받 은 후 응답 헤드 와 데 이 터 를 분석 합 니 다.
Callback () {} 리 셋 함수 에 성공 을 요청 하거나 실패 한 함 수 를 설정 합 니 다.
 
흔 한 종류
 
 
 
 
 
 
주 함수
아래 의 해석, 주요 참고: OkHttp - OkHttp 소스 코드 분석 및 OkHttp 의 디자인 사상 을 철저히 이해 합 니 다.

final class RealCall implements Call {

    ......

    //TODO                 
    Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List interceptors = new ArrayList<>();
    //TODO    okhttpClient     intercept        
    interceptors.addAll(client.interceptors());
    //TODO               
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    //TODO                        、                               
    //TODO                。  ,             。         。  ,             。
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //TODO             (                       )      
    //TODO      (If-None-Match、If-Modified-Since )        304(   )
    //TODO                
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //TODO                             
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      //TODO   okhttpClient     networkInterceptors
      //TODO                       。
      interceptors.addAll(client.networkInterceptors());
    }
    //TODO      (     、      )             、          
    //TODO   http               
    interceptors.add(new CallServerInterceptor(forWebSocket));

    //TODO      
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    boolean calledNoMoreExchanges = false;
    try {
      //TODO      
      Response response = chain.proceed(originalRequest);
      if (transmitter.isCanceled()) {
        closeQuietly(response);
        throw new IOException("Canceled");
      }
      return response;
    } catch (IOException e) {
      calledNoMoreExchanges = true;
      throw transmitter.noMoreExchanges(e);
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null);
      }
    }
  }

  ......

}

, Interceptor , okhttp , , Interceptor , , 。
,okhttp , 。
interceptors, RealInterceptorChain Interceptor.Chain, chain.proceed(originalRequest)。
chain.proceed() 。


public final class RealInterceptorChain implements Interceptor.Chain {

  ....
  
  
  public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must retain the same host and port");
    }

    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.exchange != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    //TODO        ,        index+1
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
    //TODO         -     okhttpClient,     intercept      :retryAndFollowUpInterceptor    
    Interceptor interceptor = interceptors.get(index);
    //TODO      
    Response response = interceptor.intercept(next);

    // Confirm that the next interceptor made its required call to chain.proceed().
    if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
      throw new IllegalStateException("network interceptor " + interceptor
          + " must call proceed() exactly once");
    }

    // Confirm that the intercepted response isn't null.
    if (response == null) {
      throw new NullPointerException("interceptor " + interceptor + " returned null");
    }

    if (response.body() == null) {
      throw new IllegalStateException(
          "interceptor " + interceptor + " returned a response with no body");
    }

    return response;
  }
  
  .......
  
}

, , RealInterceptorChain index+1, interceptors.get(index); Response。

, chain.proceed() , , chain.proceed() , chain.proceed() , 。

 

cache ,


public final class CacheInterceptor implements Interceptor {

    ....

    @Override 
    public Response intercept(Chain chain) throws IOException {
    //TODO   request     Response               cacheCandidate == null
    Response cacheCandidate = cache != null
        ? cache.get(chain.request())
        : null;

    //TODO         
    long now = System.currentTimeMillis();
    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
    //TODO   networkRequest == null           
    Request networkRequest = strategy.networkRequest;
    //TODO      (CacheStrategy) Response
    Response cacheResponse = strategy.cacheResponse;

    if (cache != null) {
      cache.trackResponse(strategy);
    }

    //TODO          
    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
    }

    //TODO networkRequest == null               cacheResponse == null      
    // If we're forbidden from using the network and the cache is insufficient, fail.
    if (networkRequest == null && cacheResponse == null) {
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }

    //TODO                     
    // If we don't need the network, we're done.
    if (networkRequest == null) {
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }

//     ,            。
//       ,         。

    //TODO         
    Response networkResponse = null;
    try {
      networkResponse = chain.proceed(networkRequest);
    } finally {
      // If we're crashing on I/O or otherwise, don't leak the cache body.
      if (networkResponse == null && cacheCandidate != null) {
        closeQuietly(cacheCandidate.body());
      }
    }

    //TODO             
    // If we have a cache response too, then we're doing a conditional get.
    if (cacheResponse != null) {
      //TODO 304           ,              
      if (networkResponse.code() == HTTP_NOT_MODIFIED) {
        Response response = cacheResponse.newBuilder()
            .headers(combine(cacheResponse.headers(), networkResponse.headers()))
            .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
            .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build();
        networkResponse.body().close();

        // Update the cache after combining headers but before stripping the
        // Content-Encoding header (as performed by initContentStream()).
        cache.trackConditionalCacheHit();
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }

    //TODO   Response
    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();

    if (cache != null) {
      if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
        // Offer this request to the cache.
        CacheRequest cacheRequest = cache.put(response);
        return cacheWritingResponse(cacheRequest, response);
      }

      if (HttpMethod.invalidatesCache(networkRequest.method())) {
        try {
          cache.remove(networkRequest);
        } catch (IOException ignored) {
          // The cache cannot be written.
        }
      }
    }

    return response;
  }
  
  ....
  
}

, 。
(1) ,cacheCandidate = cache.Response Response, cacheCandidate = null; CacheStrategy cacheResponse networkRequest。( )
(2) cacheCandidate != null cacheResponse == null cacheCandidate 。( , , )
(3) networkRequest == null ,cacheResponse == null , , , 。
(4) networkRequest == null ,cacheResponse != null , , , 。
( ) :
(1) ,
(2) , , , 。

, , , , , 。
okhttp 。

 

 

 

 

OkHttp   _ 2

OkHttp   _ 3

OkHttp   _ 4

OkHttp   _ 5

OkHttp   _ 6

 

https://www.jianshu.com/p/0b7cd90bec2f

 

 

좋은 웹페이지 즐겨찾기