OkHttp3-只会用是不够的,还得懂这些,成长路线图

this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
    this.callTimeout = builder.callTimeout;
    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;
  }
  //…省略代码…
  public static final class Builder {
    Dispatcher dispatcher;
    final List interceptors = new ArrayList<>();
    final List networkInterceptors = new ArrayList<>();
    //…省略部分参数…
    boolean retryOnConnectionFailure;
    int callTimeout;
    int connectTimeout;
    int readTimeout;
    int writeTimeout;
    public Builder() {
      dispatcher = new Dispatcher();
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      //…省略部分参数…
      retryOnConnectionFailure = true;
      callTimeout = 0;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
    }
    //…省略代码…
    public OkHttpClient build() {
      return new OkHttpClient(this);
    }
  }
}


这就是一个标准的构建者模式,将http请求的一些配置封装到client对象中。

#### 2\. 构建Request请求对象

public final class Request {
  final HttpUrl url;
  final String method;
  final Headers headers;
  final @Nullable RequestBody body;
  final Map<Class<?>, Object> tags;
  public static class Builder {
    @Nullable HttpUrl url;
    String method;
    Headers.Builder headers;
    @Nullable RequestBody body;
    public Builder() {
      this.method = “GET”;
      this.headers = new Headers.Builder();
    }
    Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tags = request.tags.isEmpty()
          ? Collections.emptyMap()
          : new LinkedHashMap<>(request.tags);
      this.headers = request.headers.newBuilder();
    }
  }
}


这也是一个建造者模式把请求的`url`、`method`、`header`全部封装到`Request`对象中。

### 3\. 创建Call对象

先来看看Call,这是一个接口,定义了一些`request()`、`enqueue(Callback responseCallback)`、`execute()`等方法,其实现类是RealCall,先搁置一边。回过头来看`client.newCall(request)`跟进代码,查看`newCall(Request request)`方法。

`OkHttpClient`类:

@Override   public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }


RealCall类:

static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }


果然,这里就只是跟进传进来的Request和当前的client对象创建了一个RealCall对象,也就是说使用方法中的第三步(`Call call = client.newCall(request)`)执行完成后,得到了一个ReallCall对象,接下来到了第四步。

#### 4\. 发起请求

先看`execute = call.execute()`请求

###### a).同步请求execute()

@Override
 public Response execute() throws IOException {
    synchronized (this) {
    //一个请求只能执行一次
      if (executed) throw new IllegalStateException(“Already Executed”);
      executed = true;
    }
    captureCallStackTrace();
    timeout.enter();
    //http请求调用的生命周期
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);//注释1
      Response result = getResponseWithInterceptorChain();//注释2
      if (result == null) throw new IOException(“Canceled”);
      return result;
    } catch (IOException e) {
      e = timeoutExit(e);
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }


关键代码为标出来的注释1和注释2两处,先看注释1,看下`client.dispatcher()`返回的`Dispatcher`对象:

/**
 * Policy on when async requests are executed.
 *
 * 

Each dispatcher uses an {@link ExecutorService} to run calls internally. If you supply your
 * own executor, it should be able to run {@linkplain #getMaxRequests the configured maximum} number
 * of calls concurrently.
 /public final class Dispatcher {
  //最大请求数
  private int maxRequests = 64;
  //每一个主机的最大请求数
  private int maxRequestsPerHost = 5;
  private @Nullable Runnable idleCallback;
  /
* Executes calls. Created lazily. /
  //线程池
  private @Nullable ExecutorService executorService;
  /
* Ready async calls in the order they’ll be run. /
  //准备执行的异步请求队列
  private final Deque readyAsyncCalls = new ArrayDeque<>();
  /
* Running asynchronous calls. Includes canceled calls that haven’t finished yet. /
  //正在执行的异步请求队列
  private final Deque runningAsyncCalls = new ArrayDeque<>();
  /
* Running synchronous calls. Includes canceled calls that haven’t finished yet. /
  //正在执行的同步请求队列
  private final Deque runningSyncCalls = new ArrayDeque<>();
  public Dispatcher(ExecutorService executorService) {
    this.executorService = executorService;
  }
  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);
      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.get().forWebSocket) {
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
    promoteAndExecute();
  }
  /
* Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }
//…代码略…
}


这是一个调度器,内部维护着最大请求数,每个主机最大请求数等参数,最重要的是维护着三个队列,分别是“将要执行的异步请求队列”、“正在执行的异步请求队列”和“正在执行的同步执行队列”。之前的代码段中注释1处调用`dispatcher.executed(this)`方法,我们看到这个方法只是把当前的realCall实例加入到了请求队列中。接下来看注释2处的代码`Response result = getResponseWithInterceptorChain()`,看下这个方法:

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List interceptors = new ArrayList<>();
    //用户自定义的拦截器
    interceptors.addAll(client.interceptors());
    //错误重连、重定向拦截器
    interceptors.add(retryAndFollowUpInterceptor);
    //请求配置拦截器
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //缓存拦截器
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //连接拦截器
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    //发起请求访问服务器的拦截器
    interceptors.add(new CallServerInterceptor(forWebSocket));
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
    return chain.proceed(originalRequest);
  }


在这个方法中,将用户自定义的一些拦截器和默认的拦截器封装到一个list中,然后创建`RealInterceptorChain`对象并执行`proceed(originalRequest)`方法,接下来将是重点。看一下这个方法

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    //…省去异常处理…

// Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request, call,eventListener, connectTimeout, readTimeout,writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    //…省去异常处理…
    return response;
  }


关键代码只有三行,这里会遍历调用拦截器列表中的拦截器,并调用每一个拦截器的`intercept(RealInterceptorChain chain)`方法,先看这里的第一个拦截器`RetryAndFollowUpInterceptor`的`intercept(Chain chain)`方法

@Override
 public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    //…省略部分代码…
    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
      //…省略异常处理代码…
      Response response;
      boolean releaseConnection = true;
      try {
          //注释3
        response = realChain.proceed(request, streamAllocation, null, null);
        releaseConnection = false;
      } catch (RouteException e) {
        // The attempt to connect via a route failed. The request will not have been sent.
        if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
          throw e.getFirstConnectException();
        }
        releaseConnection = false;
        continue;
      } catch (IOException e) {
        // An attempt to communicate with a server failed. The request may have been sent.
        boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
        if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
        releaseConnection = false;
        continue;
      } finally {
        // We’re throwing an unchecked exception. Release any resources.
        if (releaseConnection) {
          streamAllocation.streamFailed(null);
          streamAllocation.release(true);
        }
      }
      // Attach the prior response if it exists. Such responses never have a body.
      if (priorResponse != null) {
        response = response.newBuilder()
            .priorResponse(priorResponse.newBuilder()
                    .body(null)
                    .build())
            .build();
      }
      Request followUp;
      try {
        followUp = followUpRequest(response, streamAllocation.route());
      } catch (IOException e) {
        streamAllocation.release(true);
        throw e;
      }
      if (followUp == null) {
        streamAllocation.release(true);
        return response;
      }
      closeQuietly(response.body());
      if (++followUpCount > MAX_FOLLOW_UPS) {
        streamAllocation.release(true);
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }
      if (followUp.body() instanceof UnrepeatableRequestBody) {
        streamAllocation.release(true);
        throw new HttpRetryException(“Cannot retry streamed HTTP body”, response.code());
      }
      if (!sameConnection(response, followUp.url())) {
        streamAllocation.release(false);
        streamAllocation = new StreamAllocation(client.connectionPool(),
            createAddress(followUp.url()), call, eventListener, callStackTrace);
        this.streamAllocation = streamAllocation;
      } else if (streamAllocation.codec() != null) {
        throw new IllegalStateException(“Closing the body of " + response
            + " didn’t close its backing stream. Bad interceptor?”);
      }
      request = followUp;
      priorResponse = response;
    }
  }


在一个`while(true)`中执行,当重连次数`followUpCount`超过20次的时候,停止重连。当执行到注释3的时候,又会重新执行`RealInterceptorChain.proceed()`方法。但是这次会取出下一个拦截器`BridgeInterceptor`并执行它的`intercept(Chain chain`)方法。以这种方式就会遍历完拦截器list中的拦截器,并调用响应的`intercept`方法,接下来的几个拦截器的`intercept`方法比较简单,就不分析了。同样也会在此方法中调用`realChain.proceed()`方法进入下一个拦截器,直到最后一个拦截器`CallServerInterceptor`,看下它的`intercept`方法:

@Override public Response intercept(Chain chain) throws IOException {    final RealInterceptorChain realChain = (RealInterceptorChain) chain;    //…省略代码    realChain.eventListener().requestHeadersStart(call);       //向服务端发起请求    httpCodec.writeRequestHeaders(request);    realChain.eventListener().requestHeadersEnd(call, request);    Response.Builder responseBuilder = null;    //如果Request请求的body不为空,需要包装RequestBody并发送    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {      //…省略代码…      if (responseBuilder == null) {        if (request.body() instanceof DuplexRequestBody) {          //…省略代码…        } else {          // Write the request body if the “Expect: 100-continue” expectation was met.          realChain.eventListener().requestBodyStart(call);          //获取body内容的长度          long contentLength = request.body().contentLength();          CountingSink requestBodyOut =              new CountingSink(httpCodec.createRequestBody(request, contentLength));          BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);         //发送RequestBody          request.body().writeTo(bufferedRequestBody);          bufferedRequestBody.close();          realChain.eventListener().requestBodyEnd(call, requestBodyOut.successfulCount);        }      } else if (!connection.isMultiplexed()) {        // …省略代码…      }    }    //完成请求    if (!(request.body() instanceof DuplexRequestBody)) {      httpCodec.finishRequest();    }    if (responseBuilder == null) {      realChain.eventListener().responseHeadersStart(call);      //读取返回的Response      responseBuilder = httpCodec.readResponseHeaders(false);    }    //构建Response    responseBuilder        .request(request)        .handshake(streamAllocation.connection().handshake())        .sentRequestAtMillis(sentRequestMillis)        .receivedResponseAtMillis(System.currentTimeMillis());    Internal.instance.initCodec(responseBuilder, httpCodec);    Response response = responseBuilder.build();    //…省略了Response的code==100的处理…    if (forWebSocket && code == 101) {      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.      // 构建一个非空的Response返回    } else {      response = response.newBuilder()          .body(httpCodec.openResponseBody(response))          .build();    }    //…关闭资源…    //…异常处理…    return response;  }


下面详细分析一下这个方法:分析这个方法之前我们先看`HttpCodec`这个接口的介绍`Encodes HTTP requests and decodes HTTP responses`。编码http请求并解码http返回结果,也就是说真正的处理请求和结果的是这个接口,它有两个实现类分别是`Http1Codec`和`Http2Codec`分别对应Http/1.x和Http/2.x。

好了,开始继续之前的分析,首先通过`httpCodec.writeRequestHeaders(request)`发起请求,以`Http1Codec`为例

/**   * Prepares the HTTP headers and sends them to the server.   *   * 

For streaming requests with a body, headers must be prepared before the   * output stream has been written to. Otherwise the body would need to be buffered!   *   * 

For non-streaming requests with a body, headers must be prepared after the   * output stream has been written to and closed. This ensures that the {@code Content-Length}   * header field receives the proper value.   */  @Override public void writeRequestHeaders(Request request) throws IOException {    String requestLine = RequestLine.get(        request, streamAllocation.connection().route().proxy().type());    writeRequest(request.headers(), requestLine);  }

文末

初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。

而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。

而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。

通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。

混合式开发,微信小程序。都是得学会并且熟练的

这些是Android相关技术的内核,还有Java进阶

高级进阶必备的一些技术。像移动开发架构项目实战等

Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系

以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。

而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?

就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?

我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。

喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!

上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。

而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?

就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?

我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。

喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值