美文网首页
OkHttp 简介及源码解析

OkHttp 简介及源码解析

作者: 01_小小鱼_01 | 来源:发表于2018-06-17 11:24 被阅读8次
一、简介

OKHttp是一个网络请求的开源项目,由移动支付Square公司贡献,用于替代HttpUrlConnection和Apache HttpClient(android API23 6.0里已移除HttpClient)
其主要优点有:

  • 支持HTTP2/SPDY(共享同一个Socket来处理同一个服务器的所有请求)
  • Socket自动选择最好路线,并支持自动重连,拥有自动维护的Socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器的请求次数。
  • 基于Headers的缓存策略减少重复的网络请求。
  • 拥有Interceptors轻松处理请求与响应(自动处理GZip压缩)
二、基本用法

get的同步请求

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
Request request = new Request.Builder().url("http://www.baidu.com").build();
//创建Request 对象
Response response = null;
response = client.newCall(request).execute();//得到Response 对象
if (response.isSuccessful()) {
    Log.d("kwwl","response.code()=="+response.code());
    Log.d("kwwl","response.message()=="+response.message());
    Log.d("kwwl","res=="+response.body().string());
    //此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。
}

get的异步请求

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if(response.isSuccessful()){//回调的方法执行在子线程。
            Log.d("kwwl","获取数据成功了");
            Log.d("kwwl","response.code()=="+response.code());
            Log.d("kwwl","response.body().string()=="+response.body().string());
        }
    }
});

post 请求

OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
 
    RequestBody formBody = new FormEncodingBuilder()
    .add("platform", "android")
    .add("name", "bug")
    .add("subject", "XXXXXXXXXXXXXXX")
    .build();
 
    Request request = new Request.Builder().url(url).post(body).build();
 
    Response response = client.newCall(request).execute();
    if (response.isSuccessful()) {
        return response.body().string();
    } else {
        throw new IOException("Unexpected code " + response);
    }
}
三、源码解析

下面是关于OKHttp的请求流程图:


OKHttp的请求流程
  1. 同步请求
    同步请求调用的是 execute 方法,在内部会调用 client.dispatcher().executed(this); 方法,进去看源码可知道它实际就是将 RealCall 添加到 Dispatcher 的 runningSyncCalls 中,表示当前正在执行的同步队列中。在这里使用 Dispacther 的中 execute 仅仅只是将其添加到集合中而已,没有作别的操作,而真正执行同步任务的核心代码是 getResponseWithInterceptorChain();
public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
}

// 同步请求方法
public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    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类里面的方法
synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
}
  1. 异步请求
// 异步请求方法
public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

// Dispatcher类里面的方法
synchronized void enqueue(AsyncCall call) {
    //当正在执行的请求小于64个&&该 call 对应的主机少于5个 Call 时
    //将任务添加到 runningAsycnCalls 中,标记为正在执行的任务。
    if (runningAsyncCalls.size() < maxRequests 
        && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      //在线程池中执行这个任务。
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
}

// 实现了Runnable 接口的线程
final class AsyncCall extends NamedRunnable {
....
 protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
}
  1. 发送请求
Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> 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);
}

相关文章

网友评论

      本文标题:OkHttp 简介及源码解析

      本文链接:https://www.haomeiwen.com/subject/rifweftx.html