【0131】【okhttp框架解析与应用】

【备注】另一个框架retrofit

1.  网络框架简单概述

【cookie】代表请求的用户身份;java

 

2.网络框架源码结构分析

2.1 okhttjp的核心框架

 

2.2 核心类

 

【须要实现的抽象类】android

【实现抽象类-1】formBody只能上传简单的key-value数据;发送post请求的时候会构建formBody;json

 【实现抽象类-2】MultipartBody:能够实现对象类型的数据的上传;大的文件的上传;服务器

 

 

【request类】cookie

 

【call】网络

 

【realCall】session

 

【Header类】app

 

【DNS解析域名的类】框架

【connection相关类】ide

 

【CallBack】返回数据的回调;

【address封装了请求的数据】

【Cache模块】

【核心类】核心的方法:sendRequest;

 

【dispatcher分发类】

【流程】dispatcher将call数据放到队列中,在队列中依次执行Call,realCall对调用httpEngine,真正的构建connection和request,而后调用connect方法,获取最终的response;封装在respBody中,

而后在CallBack的onresponse方法中获取数据;

【okhttpClient类】全部流程的相互配合使用的是okhttpClient类进行配合的

 

3.网络框架的简单使用

 3.1 get请求的使用

3.2 post请求的封装

4.封装通用的网络模块

 

4.1 listener的封装

 【回调方法】定义本次的请求的处理会有哪些回调的方法进行处理;

【DisposeDataHandle.java】G:\CommonLibrary-master\CommonHttpLibrary\src\com\okhttp\listener\DisposeDataHandle.java

 1 package com.okhttp.listener;
 2 
 3 /**
 4  * 
 5  *
 6  */
 7 public class DisposeDataHandle
 8 {
 9     public DisposeDataListener mListener = null; //response的响应回调;
10     public Class<?> mClass = null;  //对应的json字节码文件
11     public String mSource = null;
12 
13     //直接将获得的json字符串抛到应用层解析;
14     public DisposeDataHandle(DisposeDataListener listener)
15     {
16         this.mListener = listener;
17     }
18 
19     //若是传递了对象,就将json文件转化为该对象的文件;
20     public DisposeDataHandle(DisposeDataListener listener, Class<?> clazz)
21     {
22         this.mListener = listener;
23         this.mClass = clazz;
24     }
25 
26     public DisposeDataHandle(DisposeDataListener listener, String source)
27     {
28         this.mListener = listener;
29         this.mSource = source;
30     }
31 }

 【封转的请求参数】以键值对的形式进行封装;G:\CommonLibrary-master\CommonHttpLibrary\src\com\okhttp\request\RequestParams.java

 1 package com.okhttp.request;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 import java.util.concurrent.ConcurrentHashMap;
 7 
 8 public class RequestParams {
 9 
10     public ConcurrentHashMap<String, String> urlParams = new ConcurrentHashMap<String, String>();
11     public ConcurrentHashMap<String, Object> fileParams = new ConcurrentHashMap<String, Object>();
12 
13     /**
14      * Constructs a new empty {@code RequestParams} instance.
15      */
16     public RequestParams() {
17         this((Map<String, String>) null);
18     }
19 
20     /**
21      * Constructs a new RequestParams instance containing the key/value string
22      * params from the specified map.
23      *
24      * @param source
25      *            the source key/value string map to add.
26      */
27     public RequestParams(Map<String, String> source) {
28         if (source != null) {
29             for (Map.Entry<String, String> entry : source.entrySet()) {
30                 put(entry.getKey(), entry.getValue());
31             }
32         }
33     }
34 
35     /**
36      * Constructs a new RequestParams instance and populate it with a single
37      * initial key/value string param.
38      *
39      * @param key
40      *            the key name for the intial param.
41      * @param value
42      *            the value string for the initial param.
43      */
44     public RequestParams(final String key, final String value) {
45         this(new HashMap<String, String>() {
46             {
47                 put(key, value);
48             }
49         });
50     }
51 
52     /**
53      * Adds a key/value string pair to the request.
54      *
55      * @param key
56      *            the key name for the new param.
57      * @param value
58      *            the value string for the new param.
59      */
60     public void put(String key, String value) {
61         if (key != null && value != null) {
62             urlParams.put(key, value);
63         }
64     }
65 
66     public void put(String key, Object object) throws FileNotFoundException {
67 
68         if (key != null) {
69             fileParams.put(key, object);
70         }
71     }
72 }

 【封装请求】G:\CommonLibrary-master\CommonHttpLibrary\src\com\okhttp\request\CommonRequest.java

[post请求]

[文件上传请求]

 

[源码]G:\CommonLibrary-master\CommonHttpLibrary\src\com\okhttp\request\CommonRequest.java

 1 package com.okhttp.request;
 2 
 3 import java.io.File;
 4 import java.util.Map;
 5 
 6 import okhttp3.FormBody;
 7 import okhttp3.Headers;
 8 import okhttp3.MediaType;
 9 import okhttp3.MultipartBody;
10 import okhttp3.Request;
11 import okhttp3.RequestBody;
12 
13 /**
14  * @author vision
15  * @function build the request
16  * 主要负责对各类请求的文件类型的封装:get/post/上传文件类型/下载文件类型;
17  */
18 public class CommonRequest {
19 
20     /**
21      * create the key-value Request
22      *
23      * @function: 将 params拼接在url后面,而后构成Request请求;
24      */
25     public static Request createPostRequest(String url, RequestParams params) {
26         FormBody.Builder mFormBodyBuild = new FormBody.Builder();
27         if (params != null) {
28             for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
29                 mFormBodyBuild.add(entry.getKey(), entry.getValue());
30             }
31         }
32         FormBody mFormBody = mFormBodyBuild.build();
33         return new Request.Builder().url(url).post(mFormBody).build();
34     }
35 
36     /**
37      * ressemble the params to the url
38      * 
39      * @param url
40      * @param params
41      * @return
42      * @function:建立一个post请求的request请求类型的对象;
43      */
44     public static Request createGetRequest(String url, RequestParams params) {
45         StringBuilder urlBuilder = new StringBuilder(url).append("?");
46         if (params != null) {
47             for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
48                 urlBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
49             }
50         }
51         return new Request.Builder().url(urlBuilder.substring(0, urlBuilder.length() - 1)).get().build();
52     }
53 
54     /**
55      * 文件上传请求
56      * 
57      * @return
58      */
59     private static final MediaType FILE_TYPE = MediaType.parse("application/octet-stream");
60 
61     public static Request createMultiPostRequest(String url, RequestParams params) {
62 
63         MultipartBody.Builder requestBody = new MultipartBody.Builder();
64         requestBody.setType(MultipartBody.FORM);
65         if (params != null) {
66 
67             for (Map.Entry<String, Object> entry : params.fileParams.entrySet()) {
68                 //判断是不是文件;
69                 if (entry.getValue() instanceof File) {
70                     //若是是文件;
71                     requestBody.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
72                             RequestBody.create(FILE_TYPE, (File) entry.getValue()));
73                 } else if (entry.getValue() instanceof String) {
74                     //若是不是文件,就当作简单的key-value值建立;
75                     requestBody.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
76                             RequestBody.create(null, (String) entry.getValue()));
77                 }
78             }
79         }
80         return new Request.Builder().url(url).post(requestBody.build()).build();
81     }
82 }

 【回调的封装】实现callBack接口;

【CommonJsonCallback.java】对json的回调的处理;G:\CommonLibrary-master\CommonHttpLibrary\src\com\okhttp\response\CommonJsonCallback.java

  1 package com.okhttp.response;
  2 
  3 import java.io.IOException;
  4 import java.util.ArrayList;
  5 
  6 import org.json.JSONObject;
  7 
  8 import com.loopj.android.http.commonhttp.ResponseEntityToModule;
  9 import com.okhttp.exception.OkHttpException;
 10 import com.okhttp.listener.DisposeDataHandle;
 11 import com.okhttp.listener.DisposeDataListener;
 12 import com.okhttp.listener.DisposeHandleCookieListener;
 13 
 14 import android.os.Handler;
 15 import android.os.Looper;
 16 import okhttp3.Call;
 17 import okhttp3.Callback;
 18 import okhttp3.Headers;
 19 import okhttp3.Response;
 20 
 21 /**
 22  * @author vision
 23  * @function 专门处理JSON的回调
 24  */
 25 public class CommonJsonCallback implements Callback {
 26 
 27     /**
 28      * the logic layer exception, may alter in different app
 29      * 【注意】此段代码是根据公司的服务器的协议进行定制的;不一样公司不一致;
 30      */
 31     // 有返回则对于http请求来讲是成功的,但还有多是业务逻辑上的错误
 32     protected final String RESULT_CODE = "ecode";
 33     protected final int RESULT_CODE_VALUE = 0;
 34     protected final String ERROR_MSG = "emsg";
 35     protected final String EMPTY_MSG = "";
 36     protected final String COOKIE_STORE = "Set-Cookie"; // decide the server it
 37                                                         // can has the value of
 38                                                         // set-cookie2
 39 
 40     /**
 41      * the java layer exception, do not same to the logic error
 42      */
 43     protected final int NETWORK_ERROR = -1; // the network relative error
 44     protected final int JSON_ERROR = -2; // the JSON relative error
 45     protected final int OTHER_ERROR = -3; // the unknow error
 46 
 47     /**
 48      * 将其它线程的数据转发到UI线程
 49      */
 50     private Handler mDeliveryHandler; //数据的转发
 51     private DisposeDataListener mListener;  //接口;
 52     private Class<?> mClass;  //要转化为的字符串的数据;
 53 
 54     public CommonJsonCallback(DisposeDataHandle handle) {
 55         this.mListener = handle.mListener;
 56         this.mClass = handle.mClass;
 57         //须要返回到主线程中,所以须要建立主线程的Looper;
 58         this.mDeliveryHandler = new Handler(Looper.getMainLooper());
 59     }
 60 
 61     //对返回数据的失败的处理
 62     @Override
 63     public void onFailure(final Call call, final IOException ioexception) {
 64         /**
 65          * 此时还在非UI线程,所以要转发
 66          */
 67         mDeliveryHandler.post(new Runnable() {
 68             @Override
 69             public void run() {
 70                 //直接回调listener中的onFailure便可;
 71                 mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
 72             }
 73         });
 74     }
 75 
 76 
 77     @Override
 78     public void onResponse(final Call call, final Response response) throws IOException {
 79         final String result = response.body().string();
 80         final ArrayList<String> cookieLists = handleCookie(response.headers());
 81         mDeliveryHandler.post(new Runnable() {
 82             @Override
 83             public void run() {
 84                 handleResponse(result);  //见105行的方法的处理;
 85                 /**
 86                  * handle the cookie
 87                  */
 88                 if (mListener instanceof DisposeHandleCookieListener) {
 89                     ((DisposeHandleCookieListener) mListener).onCookie(cookieLists);
 90                 }
 91             }
 92         });
 93     }
 94 
 95     private ArrayList<String> handleCookie(Headers headers) {
 96         ArrayList<String> tempList = new ArrayList<String>();
 97         for (int i = 0; i < headers.size(); i++) {
 98             if (headers.name(i).equalsIgnoreCase(COOKIE_STORE)) {
 99                 tempList.add(headers.value(i));
100             }
101         }
102         return tempList;
103     }
104 
105     private void handleResponse(Object responseObj) {
106         if (responseObj == null) {
107             mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG));
108             return;
109         }
110 
111         try {
112             JSONObject result = new JSONObject(responseObj.toString());
113             if (result.has(RESULT_CODE)) {
114                 if (result.optInt(RESULT_CODE) == RESULT_CODE_VALUE) {
115                     //若是没有传入返回的对象;
116                     if (mClass == null) {
117                         //直接返回到应用层;
118                         mListener.onSuccess(result);
119                     } else {
120                         //对json字符串进行解析;
121                         Object obj = ResponseEntityToModule.parseJsonObjectToModule(result, mClass);
122                         if (obj != null) {
123                             //json数据解析成功,返回给应用层;
124                             mListener.onSuccess(obj);
125                         } else {
126                             //解析失败,抛出异常;
127                             mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG));
128                         }
129                     }
130                 } else {
131                     if (result.has(ERROR_MSG)) {
132                         mListener.onFailure(
133                                 new OkHttpException(result.optInt(RESULT_CODE), result.optString(ERROR_MSG)));
134                     } else {
135                         mListener.onFailure(new OkHttpException(result.optInt(RESULT_CODE), EMPTY_MSG));
136                     }
137                 }
138             } else {
139                 if (result.has(ERROR_MSG)) {
140                     mListener.onFailure(new OkHttpException(OTHER_ERROR, result.optString(ERROR_MSG)));
141                 }
142             }
143         } catch (Exception e) {
144             mListener.onFailure(new OkHttpException(OTHER_ERROR, e.getMessage()));
145             e.printStackTrace();
146         }
147     }
148 }

 

【对文件的解析的回调的处理】

  1 package com.okhttp.response;
  2 
  3 import java.io.File;
  4 import java.io.FileOutputStream;
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 
  8 import com.okhttp.exception.OkHttpException;
  9 import com.okhttp.listener.DisposeDataHandle;
 10 import com.okhttp.listener.DisposeDownloadListener;
 11 
 12 import android.os.Handler;
 13 import android.os.Looper;
 14 import android.os.Message;
 15 import okhttp3.Call;
 16 import okhttp3.Callback;
 17 import okhttp3.Response;
 18 
 19 /**********************************************************
 20  * @文件名称:CommonFileCallback.java 23  * @文件描述:专门处理文件下载回调
 24  * @修改历史:2016年1月23日建立初始版本
 25  **********************************************************/
 26 public class CommonFileCallback implements Callback {
 27     /**
 28      * the java layer exception, do not same to the logic error
 29      */
 30     protected final int NETWORK_ERROR = -1; // the network relative error
 31     protected final int IO_ERROR = -2; // the JSON relative error
 32     protected final String EMPTY_MSG = "";
 33     /**
 34      * 将其它线程的数据转发到UI线程
 35      */
 36     private static final int PROGRESS_MESSAGE = 0x01;
 37     private Handler mDeliveryHandler;
 38     private DisposeDownloadListener mListener;
 39     private String mFilePath;
 40     private int mProgress;
 41 
 42     public CommonFileCallback(DisposeDataHandle handle) {
 43         this.mListener = (DisposeDownloadListener) handle.mListener;
 44         this.mFilePath = handle.mSource;
 45         this.mDeliveryHandler = new Handler(Looper.getMainLooper()) {
 46             @Override
 47             public void handleMessage(Message msg) {
 48                 switch (msg.what) {
 49                 case PROGRESS_MESSAGE:
 50                     mListener.onProgress((int) msg.obj);
 51                     break;
 52                 }
 53             }
 54         };
 55     }
 56 
 57     @Override
 58     public void onFailure(final Call call, final IOException ioexception) {
 59         mDeliveryHandler.post(new Runnable() {
 60             @Override
 61             public void run() {
 62                 mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
 63             }
 64         });
 65     }
 66 
 67     @Override
 68     public void onResponse(Call call, Response response) throws IOException {
 69         final File file = handleResponse(response);
 70         mDeliveryHandler.post(new Runnable() {
 71             @Override
 72             public void run() {
 73                 if (file != null) {
 74                     mListener.onSuccess(file);
 75                 } else {
 76                     mListener.onFailure(new OkHttpException(IO_ERROR, EMPTY_MSG));
 77                 }
 78             }
 79         });
 80     }
 81 
 82     /**
 83      * 此时还在子线程中,不则调用回调接口
 84      * 
 85      * @param response
 86      * @return
 87      */
 88     private File handleResponse(Response response) {
 89         if (response == null) {
 90             return null;
 91         }
 92 
 93         InputStream inputStream = null;
 94         File file = null;
 95         FileOutputStream fos = null;
 96         byte[] buffer = new byte[2048];
 97         int length = -1;
 98         int currentLength = 0;
 99         double sumLength = 0;
100         try {
101             file = new File(mFilePath);
102             fos = new FileOutputStream(file);
103             inputStream = response.body().byteStream();
104             sumLength = (double) response.body().contentLength();
105 
106             while ((length = inputStream.read(buffer)) != -1) {
107                 fos.write(buffer, 0, length);
108                 currentLength += length;
109                 mProgress = (int) (currentLength / sumLength * 100);
110                 mDeliveryHandler.obtainMessage(PROGRESS_MESSAGE, mProgress).sendToTarget();
111             }
112             fos.flush();
113         } catch (Exception e) {
114             file = null;
115         } finally {
116             try {
117                 fos.close();
118                 inputStream.close();
119             } catch (IOException e) {
120                 e.printStackTrace();
121             }
122         }
123         return file;
124     }
125 }

 

【client的封装】对整个流程的调用

  1 package com.okhttp;
  2 
  3 import java.io.InputStream;
  4 import java.util.concurrent.TimeUnit;
  5 
  6 import javax.net.ssl.HostnameVerifier;
  7 import javax.net.ssl.SSLSession;
  8 
  9 import okhttp3.Call;
 10 import okhttp3.OkHttpClient;
 11 import okhttp3.Request;
 12 
 13 import com.okhttp.cookie.SimpleCookieJar;
 14 import com.okhttp.listener.DisposeDataHandle;
 15 import com.okhttp.response.CommonFileCallback;
 16 import com.okhttp.response.CommonJsonCallback;
 17 import com.okhttp.ssl.HttpsUtils;
 18 
 19 /**
 20  * @author vision
 21  * @function 用来发送get,post请求的工具类,包括设置一些请求的共用参数,超时、https的认证等等;
 22  */
 23 public class CommonOkHttpClient
 24 {
 25     private static final int TIME_OUT = 30;
 26     private static OkHttpClient mOkHttpClient;
 27     // private static CommonOkHttpClient mClient = null;
 28 
 29     static
 30     {
 31 
 32         OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
 33         //完成对https的认证;
 34         okHttpClientBuilder.hostnameVerifier(new HostnameVerifier()
 35         {
 36             @Override
 37             public boolean verify(String hostname, SSLSession session)
 38             {
 39                 return true;
 40             }
 41         });
 42 
 43         okHttpClientBuilder.cookieJar(new SimpleCookieJar());
 44         okHttpClientBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
 45         okHttpClientBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS);
 46         okHttpClientBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);
 47         okHttpClientBuilder.followRedirects(true);//容许被重定向;
 48         /**
 49          * trust all the https point
 50          */
 51         okHttpClientBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());
 52         mOkHttpClient = okHttpClientBuilder.build();
 53     }
 54 
 55     /**
 56      * 指定cilent信任指定证书
 57      * 
 58      * @param certificates
 59      */
 60     public static void setCertificates(InputStream... certificates)
 61     {
 62         mOkHttpClient.newBuilder().sslSocketFactory(HttpsUtils.getSslSocketFactory(certificates, null, null)).build();
 63     }
 64 
 65     /**
 66      * 指定client信任全部证书
 67      */
 68     public static void setCertificates()
 69     {
 70         mOkHttpClient.newBuilder().sslSocketFactory(HttpsUtils.getSslSocketFactory());
 71     }
 72 
 73     /**
 74      * 经过构造好的Request,Callback去发送请求
 75      * 
 76      * @param request
 77      * @param callback
 78      */
 79     /*get请求*/
 80     public static Call get(Request request, DisposeDataHandle handle)
 81     {
 82         Call call = mOkHttpClient.newCall(request);
 83         call.enqueue(new CommonJsonCallback(handle));
 84         return call;
 85     }
 86     /*post请求*/
 87     public static Call post(Request request, DisposeDataHandle handle)
 88     {
 89         Call call = mOkHttpClient.newCall(request);
 90         call.enqueue(new CommonJsonCallback(handle));
 91         return call;
 92     }
 93     /*文件下载*/
 94     public static Call downloadFile(Request request, DisposeDataHandle handle)
 95     {
 96         Call call = mOkHttpClient.newCall(request);
 97         call.enqueue(new CommonFileCallback(handle));
 98         return call;
 99     }
100 }

5.测试

【get请求的调用】

【post请求的调用】

【下载文件的请求】

【上传文件的响应】

【对点击事件的响应】

 

相关文章
相关标签/搜索