Okhttp学习笔记(一) 初步认识&& 源码浅析

学习资料:

BAT大牛带你深度剖析Android 十大开源框架

同步请求

发起请求后,会进入阻塞状态,直到收到响应

使用步骤

  • 创建一个OkHttpClient对象
  • 构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象
  • 执行call的execute方法

源码浅析

创建okhttpclient

    // 建造者模式
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new RetryInterceptor())
            .addInterceptor(new LogInterceptor())
            .connectTimeout(CONNECT_TIMEOUT_MILLIS, 
            TimeUnit.MILLISECONDS)
            .readTimeout(READ_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS)
            .writeTimeout(WRITE_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS)
            .build();

okhttpclient使用了建造者模式,看一下Builder,只列了一些基本的,后续慢慢学慢慢补上


//构造方法
public Builder() { 
  dispatcher = new Dispatcher();    // 请求分发 在这里初始化了一个分发器
  connectionPool = new ConnectionPool(); // 连接池
  ...
  connectTimeout = 10_000; // 默认10秒
  readTimeout = 10_000; // 默认10秒
  ...
}

// 其中一个方法 添加拦截器
public Builder addInterceptor(Interceptor interceptor) {  
    if (interceptor == null) throw new IllegalArgumentException("interceptor == null"); 
    interceptors.add(interceptor);  
    return this;
}

// 最后调用build方法
public OkHttpClient build() { 
    return new OkHttpClient(this);
}

OkHttpClient类
构造器接收一个Builder参数,如果没有传入,则会新建一个默认的Builder,然后把Builder的参数给到OkHttpClient。


 public OkHttpClient() {
    this(new Builder());
  }
  
OkHttpClient(Builder builder) {
    this.dispatcher = builder.dispatcher; // 重要的一个分发类
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.eventListenerFactory = builder.eventListenerFactory;
    this.proxySelector = builder.proxySelector;
    this.cookieJar = builder.cookieJar;
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;
    this.socketFactory = builder.socketFactory;
    ...
 }

构建Request对象

构建

Request request = new Request.Builder()
                .url("www.baidu.com") // 传入url地址
                .get()  // get请求
                .headers(mHeadBuilder.build()) // 传入请求头
                .build();

Request类同样使用建造者模式,Request.Builder:

  public static class Builder {
    HttpUrl url; // url 里面有scheme、host、port等数据
    String method; // “GET” 或者 “POST”
    Headers.Builder headers; // 请求头,这里传入的是他的Builder
    RequestBody body;

    // 默认参数,可以看到默认为GET请求
    public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
    }

    /** Removes all headers on this builder and adds {@code headers}. */
    /** 移除这个构建器所有的请求头,并添加 */
    public Builder headers(Headers headers) {
      this.headers = headers.newBuilder();
      return this;
    }
    
    // build方法返回 Request
    public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }
       
  }

Headers类,用于添加请求头等参数
看一下上面用到的newBuilder方法

 public Builder newBuilder() {
    Builder result = new Builder();
    Collections.addAll(result.namesAndValues, namesAndValues);
    return result;
  }
  namesAndValues在Headers.Builder是一个List,在Headers会被转换成一个String[]
   public static final class Builder {
    final List<String> namesAndValues = new ArrayList<>(20);
    }
    
    public final class Headers {
      private final String[] namesAndValues;
    }

Request类
把传入的Builder中的参数赋值

public final class Request {
  final HttpUrl url;
  final String method;
  final Headers headers;
  final @Nullable RequestBody body;
  final Map<Class<?>, Object> tags;

  private volatile CacheControl cacheControl; // Lazily initialized.

  Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tags = Util.immutableMap(builder.tags);
  }
}

构建Call对象

使用前面构建的 client和request,执行client的newCall方法构建Call对象
Call对象代表一个网络请求

 Call call = client.newCall(request);

 // client 中的newCall方法 RealCall.newRealCall方法具体见下面
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false);
  }
  

Call 是一个接口,真正执行的是他的实现类RealCall

public interface Call extends Cloneable {
  /** 返回初始的request对象 */
  Request request();

  Response execute() throws IOException;
  void enqueue(Callback responseCallback);

 /*是否已经执行请求*/
  boolean isExecuted();
  boolean isCanceled();
  Call clone();
  interface Factory {
    Call newCall(Request request);
  }
}

RealCall


 private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client; // 持有
    this.originalRequest = originalRequest; // 持有
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); // 重定向拦截器
  }


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;
  }

完成同步请求

执行call.execute();就完成了一次同步请求,并获取response响应对象

        try {
            Response response = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

真正执行的是RealCall.execute()

@Override public Response execute() throws IOException {
    // 确保每个请求只请求一次
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace(); // 捕捉异常堆栈信息
    eventListener.callStart(this); // 监听事件 监听每次call执行请求(同步或者异步)
    try {
      client.dispatcher().executed(this); // 重点 执行 添加到队列

      // 获取拦截器链,获取请求结果
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this); // 重点 回收
    }
  }

可以看到真正执行的是调用了是Dispatcher分发器类执行的executed和finish
Dispatcher:

/---------------保存同步请求、移除同步请求-----------------/

synchronized void executed(RealCall call) {
    runningSyncCalls.add(call); //添加到队列,保存同步请求
  }

 /-----------------回收同步请求----------------------------/
  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
  }

  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      // 移除同步请求
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls(); // 异步会调用的方法
      runningCallsCount = runningCallsCount(); // 获取正在执行的请求数
      idleCallback = this.idleCallback;
    }
     // 执行数为0时,且idleCallback 不为空,执行idleCallback.run();
    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

异步请求

  • 创建一个okhttpClient对象
  • 构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象
  • 执行call的enqueue方法

前两步都是一样的,只有第三步是不一样的,主要看一下第三步
(强调:回调的两个方法都处于工作线程)

完成异步请求

// enqueue方法: 需要传入一个Callback 对象,用于接收返回值
void enqueue(Callback responseCallback);

// 前两步获取到的call对象,执行enqueue方法
call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });

源码浅析

上面提到真正执行的是 Call接口的实现类RealCall

@Override public void enqueue(Callback responseCallback) {

    // Call只能执行一次
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace(); // 捕捉异常信息
    eventListener.callStart(this);
    // 关键 封装了一个AsyncCall对象
    client.dispatcher().enqueue(new AsyncCall(responseCallback)); 
  }

AsyncCall对象:继承于NameRunable (实现了 Runnable接口)

Dispatcher()的enqueue方法

synchronized void enqueue(AsyncCall call) {
    // maxRequests 和 maxRequestsPerHost 是定义的常量,规定了最大的请求数、最大主机请求数
    // 判断是否小于最大数,若是,则添加进请求队列中,并调用线程池执行(AsyncCall 实现了Runnable)
    // 如果超过了最大值,则添加到缓存等待的请求队列
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call); // 调用线程词执行
    } else {
      readyAsyncCalls.add(call);
    }
  }

小结:

  • 先判断是否已经执行
  • 将Call封装成一个AsyncCall对象
  • 调用client.dispatcher().enqueque(AsyncCall asyncCall)【判断是否超过最大值,添加、执行请求】

那么接下来的重点就是

executorService().execute(AsyncCall call);

executorService().execute() 方法

源码:

 public synchronized ExecutorService executorService() {
      // 保持单例 核心线程为 0
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

创建后执行:线程词会调用子线程的run方法,AsyncCall 继承于 NameRunnnable,并且重写了execute方法,而在NameRunnable里,实现了run方法但是只是把execute这个抽象方法包装起来,所以具体实现在AsyncCall的execute方法:

 final class AsyncCall extends NamedRunnable {

    ...
    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
      // 获取拦截器链 获取response
        Response response = getResponseWithInterceptorChain();
        // 判断是否取消
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          // 取消则回调onFailure
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          // 没取消则回调onResponse
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          // 捕获到异常 回调到onFailure方法
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        // 调用finished方法
        client.dispatcher().finished(this);
      }
    }
    ...
 }

总结:

  • 先判断是否已经执行
  • 将Call封装成一个AsyncCall对象
  • 调用client.dispatcher().enqueque(AsyncCall asyncCall)【判断是否超过最大值,添加、执行请求】

而后:

  • dispatcher().enqueque 方法进行了判断,如果没有超过请求的最大数值和主机数值,则会调用线程池执行AsyncCall 中的execute方法
  • AsyncCall 中的execute方法 通过getResponseWithInterceptorChain()方法获取到了response,之后进行一系列的判断,回调到onResponse或者onFailure方法

关于Dispatcher类详解:

Okhttp学习笔记(二)核心之一:Dispatcher

发布了27 篇原创文章 · 获赞 6 · 访问量 1654

猜你喜欢

转载自blog.csdn.net/weixin_41802023/article/details/102678129