美文网首页
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