——谁不是一边受伤一边成长,谁不是一面流泪一面坚强。
这篇给Okhttp做个记录。主要还是对自己阅读源码后的一个总结。当然距离上次看过源码已经1年多。写这篇的原因还是担心过太久又忘了。 所以复习并总结一下。本篇不会有太多的拓展,主要以介绍性为主。
github地址: GitHub
——是目前最火的开源网络请求框架。有人可能会想到Retrofit,当然Retrofit也是基于okhttp的一个二次封装库。
——提供更方便的网络请求方式。通过该库可以更加简洁的获取到网络数据。
步骤:
(1)添加依赖
implementation "com.squareup.okhttp3:okhttp:3.5.0"复制代码
(2)创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient();复制代码
(3)构建Request请求信息
//构建请求信息:连接请求url 请求方法method 请求头部headers 请求体body 标签tag Request request = new Request.Builder().url("xxxxxx").get().build();复制代码
(4)创建Call对象
Call call = okHttpClient.newCall(request);复制代码
(5)创建同步请求
try { Call call = okHttpClient.newCall(request); Response execute = call.execute(); String success = execute.body().toString(); Log.e(TAG, "onCreate: "+success ); } catch (IOException e) { e.printStackTrace(); }复制代码
(6)创建异步请求
okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });复制代码
(7)总结
//创建OkhttpClient OkHttpClient okHttpClient = new OkHttpClient(); //构建请求信息:连接请求url 请求方法method 请求头部headers 请求体body 标签tag Request request = new Request.Builder().url("xxxxxx").get().build(); //同步 try { Call call = okHttpClient.newCall(request); Response execute = call.execute(); String success = execute.body().toString(); Log.e(TAG, "onCreate: "+success ); } catch (IOException e) { e.printStackTrace(); } //异步 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });复制代码
(1)创建OkHttpClient:OkHttpClient okHttpClient = new OkHttpClient();
//1.创建OkhttpClient 有两种方式 (1)OkHttpClient okHttpClient = new OkHttpClient(); (2)OkHttpClient build = new OkHttpClient.Builder().build(); 第一种OkhttpClient 采用默认配置信息 第二种通过Builder 可自定义配置信息 //默认配置 Builder() public OkHttpClient() { this(new Builder()); } //OkhttpClient 配置信息 public Builder() { //创建Dispatcher: 该对象内部维护着一个线程池, //管理OkhttpClient的线程操作。通过该对象可执行异步操作。 dispatcher = new Dispatcher(); protocols = DEFAULT_PROTOCOLS;//定义默认协议 connectionSpecs = DEFAULT_CONNECTION_SPECS;//定义连接方式 proxySelector = ProxySelector.getDefault();//使用默认代理服务 cookieJar = CookieJar.NO_COOKIES;//定义 Cookie socketFactory = SocketFactory.getDefault();//使用默认的SocketFactory hostnameVerifier = OkHostnameVerifier.INSTANCE;//定义默认证书 certificatePinner = CertificatePinner.DEFAULT;//定义不受信任的证书 //设置网络身份验证 proxyAuthenticator = Authenticator.NONE; authenticator = Authenticator.NONE; //连接池:管理HTTP和HTTP/2连接的重用,以减少网络延迟 connectionPool = new ConnectionPool(); dns = Dns.SYSTEM; //定义HTTPS 和 HTTP 之间的重定向 followSslRedirects = true; followRedirects = true; //定义是否失败重连 retryOnConnectionFailure = true; //定义连接超时连接 connectTimeout = 10_000; //定义读取超时连接 readTimeout = 10_000; //定义写入超时连接 writeTimeout = 10_000; //定义Web socket ping 间隔 pingInterval = 0; }复制代码
进阶:还可以通过addNetworkInterceptor(Interceptor interceptor)与addInterceptor(Interceptor interceptor)添加自定义拦截器
addInterceptor()方法添加的拦截器是放在addNetworkInterceptor()前面的。
addNetworkInterceptor() 方法添加的网络拦截器,则是在非 WebSocket 请求时。
添加在 ConnectInterceptor 和 CallServerInterceptor 之间的。
addInterceptor(应用拦截器):
1,不需要担心中间过程的响应,如重定向和重试.
2,总是只调用一次,即使HTTP响应是从缓存中获取.
3,观察应用程序的初衷. 不关心OkHttp注入的头信息如: If-None-Match.
4,允许短路而不调用 Chain.proceed(),即中止调用.
5,允许重试,使 Chain.proceed()调用多次.
addNetworkInterceptor(网络拦截器):
1,能够操作中间过程的响应,如重定向和重试.
2,当网络短路而返回缓存响应时不被调用.
3,只观察在网络上传输的数据.
4,携带请求来访问连接.
(2)构建Request请求信息:Request request = new Request.Builder().url("xxxxxx").get().build();
//请求信息 public final class Request { final HttpUrl url; //配置url final String method;//配置请求方法 final Headers headers;// 配置请求头部 final RequestBody body;//配置请求体 final Object tag; //标记请求 } //使用默认get请求 与默认头部 public Builder() { this.method = "GET"; this.headers = new Headers.Builder(); } //创建Request 请求 public Request build() { if (url == null) throw new IllegalStateException("url == null"); return new Request(this); } //配置Request 信息 Request(Builder builder) { this.url = builder.url; this.method = builder.method; this.headers = builder.headers.build(); this.body = builder.body; this.tag = builder.tag != null ? builder.tag : this; }复制代码
(3)OkHttpClient 关联 Request: Call call = okHttpClient.newCall(request);
/** * 1.创建 RealCall() */ @Override public Call newCall(Request request) { return new RealCall(this, request, false /* for web socket */); } /** * 2. RealCall 持有 OkHttpClient对象与Request对象 并创建 重定向拦截器 * 主要作用是发起请求 */ RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { this.client = client; this.originalRequest = originalRequest; this.forWebSocket = forWebSocket; this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); } /** * 3.重定向拦截器 持有OkHttpClient 对象 */ public RetryAndFollowUpInterceptor(OkHttpClient client, boolean forWebSocket) { this.client = client; this.forWebSocket = forWebSocket; }复制代码
(4)发起请求
//同步请求
//调用 RealCall 对象execute() 发起同步请求 @Override public Response execute() throws IOException { synchronized (this) { //判断是否在执行 if (executed) throw new IllegalStateException("Already Executed"); executed = true; } //将一些堆栈跟踪的信息存储于重定向拦截器 captureCallStackTrace(); try { //将Call添加到同步运行队列中 client.dispatcher().executed(this); //通过okHttpClient调用调度器(dispatcher)执行拦截器链 ——> (1) Response result = getResponseWithInterceptorChain(); if (result == null) throw new IOException("Canceled"); return result; } finally { client.dispatcher().finished(this); } } // (1)通过okHttpClient调用调度器(dispatcher)执行拦截器链: // 主要作用:连接服务器,处理请求体与响应体。最终获取到Response 数据。 // okHttpClient 核心方法 Response getResponseWithInterceptorChain() throws IOException { // 1.创建容器存储拦截器 List<Interceptor> interceptors = new ArrayList<>(); // 2.添加自定义拦截器 interceptors.addAll(client.interceptors()); // 3.添加重定向拦截器 主要作用 //(1)根据异常结果或者响应结果判断是否要进行重新请求 interceptors.add(retryAndFollowUpInterceptor); // 4.添加网络连接桥拦截器 主要作用: //(1)将用户构建的一个 Request 请求转化为能够进行网络访问的请求 //(2)将网络请求回来的响应 Response 转化为用户可用的 Response interceptors.add(new BridgeInterceptor(client.cookieJar())); // 5.添加缓存拦截器 主要作用: // (1)创建缓存策略 缓存响应数据 interceptors.add(new CacheInterceptor(client.internalCache())); // 6.添加连接拦截器 主要作用: // (1)与服务端 建立连接,并且获得通向服务端的输入和输出流对象 interceptors.add(new ConnectInterceptor(client)); if (!forWebSocket) { // 7.添加 自定义网络拦截器 interceptors.addAll(client.networkInterceptors()); } // 8.添加 服务回调拦截器 主要作用: // (1)使用 HttpStream 与服务器进行数据的读写操作的 interceptors.add(new CallServerInterceptor(forWebSocket)); // 9.创建拦截器链 并启动 Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }复制代码
//异步请求
//调用该方法 执行异步请求 @Override public void enqueue(Callback responseCallback) { //判断是否重复执行 synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } //将一些堆栈跟踪的信息存储于重定向拦截器 captureCallStackTrace(); // 详情——> (1) (2) client.dispatcher().enqueue(new AsyncCall(responseCallback)); } (1)异步请求策略 synchronized void enqueue(AsyncCall call) { //判断运行的异步线程数是否小于最大的请求数 核心线程数小于最大的运行数 if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { // 运行的异步线程数未满 则执行新的任务caLl runningAsyncCalls.add(call); executorService().execute(call); } else { // 运行的异步线程数达到最大值 则将新的任务添加到等待的队列中 readyAsyncCalls.add(call); } } (2)创建AsyncCall 继承NamedRunnable 对象 并执行NamedRunnable 的run() @Override public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(name); try { //——> (3) execute(); } finally { Thread.currentThread().setName(oldName); } } (3) 最终执行AsyncCall 的 execute() @Override protected void execute() { boolean signalledCallback = false; try { //同样执行拦截器链 获取到Response 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 { responseCallback.onFailure(RealCall.this, e); } } finally { client.dispatcher().finished(this); } } }复制代码
通过源码可以清楚的了解到,OKHTTP 该库获取网络请求数据的核心实现是通过责任链模式。
由各个拦截器协作完成对网络服务器的数据获取。
重要的过程还是要通过了解各个拦截器实现。才能清楚如何连接网络。并获取到数据。
这里就不详细记录。 谢谢各位浏览。 。。。