关于android:Android-网络请求之OKHttp3

Android 网络申请之OKHttp3

OKHttp是一个第三方类库,用于Android申请网络,这是一个开源我的项目是Android最炽热的轻量
一:援用

 implementation 'com.squareup.okhttp3:okhttp:3.8.0'//OKHttp3网络申请框架
    implementation 'com.squareup.okio:okio:1.12.0'//Android OKHttp3应用须要增加一个收入IO的okio包

二:一个简略的okhttp应用

//第一步:构建者模式,创立实例
        OkHttpClient mClient=new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)//设置连贯超时20s
                .build();
        //第二步,构建者模式,创立申请信息
        Request mRequest=new Request.Builder()
                .get()
                .url("https://www.baidu.com")
                .build();
        //第三步,将request转成call
        Call call=mClient.newCall(mRequest);
        //第四步,执行call申请的,异步
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()){
                    //响应胜利后,拿到响应体
                    final String body= response.body().string();
                    //切换回主线程等
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //主线程
                        }
                    });
                }


            }
        });

这样的话,咱们只能相当于应用的是异步的get申请,还有同步申请,以及post申请,等等,故咱们须要对其进行封装
下面创立OkHttp只是一个简略的,还有其余属性

final Dispatcher dispatcher;//调度器
    final Proxy proxy;//代理
    final List<Protocol> protocols;//协定
    final List<ConnectionSpec> connectionSpecs;//传输层版本和连贯协定
    final List<Interceptor> interceptors;//拦截器
    final List<Interceptor> networkInterceptors;//网络拦截器
    final EventListener.Factory eventListenerFactory;
    final ProxySelector proxySelector;//代理选择器
    final CookieJar cookieJar;//cookie
    final Cache cache;//cache 缓存
    final InternalCache internalCache;//外部缓存
    final SocketFactory socketFactory;//socket 工厂
    final SSLSocketFactory sslSocketFactory;//安全套层socket工厂 用于https
    final CertificateChainCleaner certificateChainCleaner;//验证确认响应书,实用HTTPS 申请连贯的主机名
    final HostnameVerifier hostnameVerifier;//主机名字确认
    final CertificatePinner certificatePinner;//证书链
    final Authenticator proxyAuthenticator;//代理身份验证
    final Authenticator authenticator;//本地省份验证
    final ConnectionPool connectionPool;//链接池 复用连贯
    final Dns dns; //域名
    final boolean followSslRedirects;//安全套接层重定向
    final boolean followRedirects;//本地重定向
    final boolean retryOnConnectionFailure;//重试连贯失败
    final int connectTimeout;//连贯超时
    final int readTimeout;//读取超时
    final int writeTimeout;//写入超时

第 1 步就是用构建者模式创立okhttp3的实例,外面封装了一些应用中必要的属性,如超时工夫,拦截器等

OKhttp拦截器是一种弱小的机制,能够监督,重写和重试Call申请
Okhttp中拦截器分2个APP层面的拦截器和网络申请层面的拦截器
Application Interceptor

不须要放心是否影响OKHttp的申请策略和申请速度
即便从缓存中取数据,也会执行Application拦截器
容许重试,即Chain.proceed()能够执行屡次。
能够监听察看这个申请的最原始的未扭转的用意(申请头,申请体等),无奈操作OKHttp为咱们主动增加额定的申请头
无奈操作两头的响应后果,比方当URL重定向产生以及申请重试,只能操作客户端被动第一次申请以及最终的响应后果
Network Interceptors

能够批改OkHttp框架主动增加的一些属性,即容许操作两头响应,比方当申请操作产生重定向或者重试等。
能够察看最终残缺的申请参数(也就是最终服务器接管到的申请数据和相熟)

//利用拦截器
 Interceptor appInterceptor=new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                 // get token
            String token = AppService.getToken();
            Request originalRequest = chain.request();
            // get new request, add request header
            Request updateRequest = originalRequest.newBuilder()
                    .header("token", token)
                    .build();
                Response response = chain.proceed(updateRequest );//申请
                Log.d("TAG", "app intercept:end");
                return response ;
            }
        };
        
        /**
     * 网络拦截器
     */
    Interceptor networkInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Log.d(TAG,"network interceptor:begin");
                    Response  response = chain.proceed(request);//申请
                    Log.d(TAG,"network interceptor:end");
                    return response;
                }
            };
            
     //应用
      okHttpClient = new OkHttpClient
                .Builder()
                .addInterceptor(appInterceptor)
                .addNetworkInterceptor(networkInterceptor)
                .build();


三:Request的创立

  final HttpUrl url; // 接口地址
  final String method; // post还是get
  final Headers headers; // Http音讯的头字段
  final RequestBody body; // 它是抽象类, 有些申请须要咱们传入body实例,如果是GET申请,body对象传的是null,如果是POST申请,就须要咱们去设定了。
  final Object tag;

第 2 步就是用构建者模式创立申请信息的实例,外面封装了一些应用中必要的属性,如申请形式,申请头信息,接口地址等
四:Call对象的创立

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

第 3 步就是创立realcall对象,真正的申请是交给了 RealCall 类,它实现了Call办法,它是真正的外围代码。
五:realcall的异步申请

//调用
`call.enqueue(new Callback(){ ... });`
//源码
@Override 
public void enqueue(Callback responseCallback) {
    1.synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    2.client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
  synchronized (this) 确保每个call只能被执行一次不能反复执行,如果想要完全相同的call,能够调用如下办法:进行克隆
利用dispatcher调度器,来进行理论的执行client.dispatcher().enqueue(new AsyncCall(responseCallback)), 这里分为2步走

//看一下new AsyncCall(responseCallback)

 final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }
 }

总结一下
在call.enqueue(new Callback(){ … }) 执行之后,首先做的是

  1. 调用RealCall.call.enqueue()办法,判断以后call是否曾经被执行过了,被执行过了,就抛出异样,如果没有执行过,就先将callback封装成AsyncCall,而后调用dispatcher.enqueue()办法(dispatcher调度器,在okHttpClient外面创立的)
  2. 在dispatcher.enqueue()办法中,判断以后正在执行的申请数及以后网络申请的主机数是否超过了最大值。要是超过了最大值,就将申请放到期待队列中,要是没超过,就放当正在执行的队列中,而后调用线程池执行它。
    四:相干封装实例
public class NetRequest {
    private static NetRequest netRequest;
    private static OkHttpClient okHttpClient;//OKHttp网络申请
    private Handler mHandler;
    private NetRequest() {
        //初始化okHttp,创立一个OKhttpClient对象,一个app里最好实例化一个此对象
        okHttpClient=new OkHttpClient();
        okHttpClient.newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10,TimeUnit.SECONDS)
                .writeTimeout(10,TimeUnit.SECONDS);
        //Handler线程
        mHandler=new Handler(Looper.getMainLooper());

    }
    /**
     * 单例模式获取NetRequest实例*/
    private static NetRequest getInstance(){
        if (netRequest==null){
            netRequest=new NetRequest();
        }
        return netRequest;
    }

    //

    /**
     * 建设网络框架,获取网络数据,异步get申请(Form)
     *
     * @param url      url
     * @param params   key value
     * @param callBack data
     */
    public static void getFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
        getInstance().inner_getFormAsync(url, params, callBack);
    }

    /**
     * 建设网络框架,获取网络数据,异步post申请(Form)
     *
     * @param url      url
     * @param params   key value
     * @param callBack data
     */
    public static void postFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
        getInstance().inner_postFormAsync(url, params, callBack);
    }
    /**
     * 建设网络框架,获取网络数据,异步post申请(json)
     *
     * @param url      url
     * @param params   key value
     * @param callBack data
     */
    public static void postJsonRequest(String url, Map<String, String> params, DataCallBack callBack) {
        getInstance().inner_postJsonAsync(url, params, callBack);
    }

    /**
     * 异步get申请(Form),外部实现办法
     *
     * @param url    url
     * @param params key value
     */
    private void inner_getFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
        if (params == null) {
            params = new HashMap<>();
        }
        // 申请url(baseUrl+参数)
        final String doUrl = urlJoint(url, params);
        // 新建一个申请
        final Request request = new Request.Builder().url(doUrl).build();
        //执行申请取得响应后果
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) { // 申请胜利
                    //执行申请胜利的操作
                    String result = response.body().string();
                    deliverDataSuccess(result, callBack);
                } else {
                    throw new IOException(response + "");
                }
            }
        });
    }

    /**
     * 异步post申请(Form),外部实现办法
     *
     * @param url      url
     * @param params   params
     * @param callBack callBack
     */
    private void inner_postFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
        RequestBody requestBody;
        if (params == null) {
            params = new HashMap<>();
        }
        FormBody.Builder builder = new FormBody.Builder();
        /**
         * 在这对增加的参数进行遍历
         */
        for (Map.Entry<String, String> map : params.entrySet()) {
            String key = map.getKey();
            String value;
            /**
             * 判断值是否是空的
             */
            if (map.getValue() == null) {
                value = "";
            } else {
                value = map.getValue();
            }
            /**
             * 把key和value增加到formbody中
             */
            builder.add(key, value);
        }
        requestBody = builder.build();
        //后果返回
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) { // 申请胜利
                    //执行申请胜利的操作
                    String result = response.body().string();
                    deliverDataSuccess(result, callBack);
                } else {
                    throw new IOException(response + "");
                }
            }
        });
    }

    /**
     * post申请传json
     *
     * @param url      url
     * @param callBack 胜利或失败回调
     * @param params   params
     */
    private void inner_postJsonAsync(String url, Map<String, String> params, final DataCallBack callBack) {
        // 将map转换成json,须要引入Gson包
        String mapToJson = new Gson().toJson(params);
        final Request request = buildJsonPostRequest(url, mapToJson);
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) { // 申请胜利
                    //执行申请胜利的操作
                    String result = response.body().string();
                    deliverDataSuccess(result, callBack);
                } else {
                    throw new IOException(response + "");
                }
            }
        });
    }
    /**
     * Json_POST申请参数
     *
     * @param url  url
     * @param json json
     * @return requestBody
     */
    private Request buildJsonPostRequest(String url, String json) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        return new Request.Builder().url(url).post(requestBody).build();
    }



    /**
     * 散发失败的时候调用
     *
     * @param request  request
     * @param e        e
     * @param callBack callBack
     */
    private void deliverDataFailure(final Request request, final IOException e, final DataCallBack callBack) {
        /**
         * 在这里应用异步解决
         */
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    callBack.requestFailure(request, e);
                }
            }
        });
    }

    /**
     * 散发胜利的时候调用
     *
     * @param result   result
     * @param callBack callBack
     */
    private void deliverDataSuccess(final String result, final DataCallBack callBack) {
        /**
         * 在这里应用异步线程解决
         */
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        callBack.requestSuccess(result);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 数据回调接口
     */
    public interface DataCallBack {

        void requestSuccess(String result) throws Exception;

        void requestFailure(Request request, IOException e);
    }


    /**
     * 拼接url和申请参数
     *
     * @param url    url
     * @param params key value
     * @return String url
     */
    private static String urlJoint(String url, Map<String, String> params) {
        StringBuilder endUrl = new StringBuilder(url);
        boolean isFirst = true;
        Set<Map.Entry<String, String>> entrySet = params.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            if (isFirst && !url.contains("?")) {
                isFirst = false;
                endUrl.append("?");
            } else {
                endUrl.append("&");
            }
            endUrl.append(entry.getKey());
            endUrl.append("=");
            endUrl.append(entry.getValue());
        }
        return endUrl.toString();
    }

}

END:用于实际,基于原理

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理