国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

OkHttp中Interceptor攔截器之公共參數請求封裝

2019-11-07 23:26:14
字體:
來源:轉載
供稿:網友

前言

之前在面試的時候遇到這樣的一個問題,那就是如果app中所有的請求都要加入一些參數(例如 版本號、手機號、登錄用戶名、token等。。。)那么怎么做才能實現,而不至于在每次請求的時候都去進行添加這些請求頭。其實這個問題,剛開始我是拒絕的(之前沒有遇到過這樣的需求)。當時只是想著可以使用okhttp體用的攔截器Interceptor來進行實現,但是具體的實現還是來到了今天。

Interceptor說明

在okhttp-wiki里面專門有一篇介紹Interceptor的(點擊我跳轉到Interceptor鏈接)里面有這樣的一句話

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls. 攔截器是一種強大的機制,可以監視、重寫和重試調用

Interceptor幾大作用
application Interceptors 應用攔截器Network Interceptors 網絡攔截器Choosing between application and network interceptors 在應用和網絡攔截器之間做選擇Rewriting Requests 重寫請求Rewriting Responses 重寫響應

具體的作用簡介這里不再贅述,這里推薦一篇翻譯的文章(Okhttp-wiki 之 Interceptors 攔截器)

進入主題

先來看下我們的需求

需求約束

1、API Base Url : http://111.111.111.11:8082/xxxxx/xx(類似)

2、客戶端請求API的數據格式為json形式:

{ "publicParams":{}, "key1":value, "key2":value}

其中publicParams為公共參數,每個API接口必須傳遞

3、公共參數

字段 類型 說明
imei string 移動設備身份(非必須)
model 手機型號、設備名稱
la string 系統語言
resolution string 分辨率(格式:1920*1080)
densityScaleFactor string 密度比例
sdk int SDK版本號
os string 系統源代碼控制值

解決方法

我們就是利用Interceptor攔截器,對每次的網絡請求進行攔截,然后拿到請求url,并對url進行改造來加入我們需要的公共參數,進行和請求參數的拼接,然后構造request,通過chain.PRoceed(request)進行改造。

第一步

構建一個CommonParamsInterceptor.class類繼承自Interceptor復寫intercept(Chain chain)方法,我們需要用到chain.request()來獲取到request對象request里面的方法

這里我們只需要用到url()方法(主要獲取到api地址和請求參數,并進行改造),用到method()方法來判斷get請求和post請求。 這個時候我們看下代碼怎么進行編寫吧。 @Override public Response intercept(Chain chain) throws IOException { //獲取到request Request request = chain.request(); //獲取到方法 String method = request.method(); //公共參數hasmap try { //添加公共參數 HashMap<String, Object> commomParamsMap = new HashMap<>(); commomParamsMap.put(Constants.IMEI, DeviceUtils.getIMEI(mContext)); commomParamsMap.put(Constants.MODEL, DeviceUtils.getModel()); commomParamsMap.put(Constants.LANGUAGE, DeviceUtils.getLanguage()); commomParamsMap.put(Constants.os, DeviceUtils.getBuildVersionIncremental()); commomParamsMap.put(Constants.RESOLUTION, DensityUtil.getScreenW(mContext) + "*" + DensityUtil.getScreenH(mContext)); commomParamsMap.put(Constants.SDK, DeviceUtils.getBuildVersionSDK() + ""); commomParamsMap.put(Constants.DENSITY_SCALE_FACTOR, mContext.getResources().getDisplayMetrics().density + ""); //get請求的封裝 if (method.equals("GET")) { //獲取到請求地址api HttpUrl httpUrlurl = request.url(); HashMap<String, Object> rootMap = new HashMap<>(); //通過請求地址(最初始的請求地址)獲取到參數列表 Set<String> parameterNames = httpUrlurl.queryParameterNames(); for (String key : parameterNames) { //循環參數列表 if (Constants.PARM.equals(key)) { //判斷是否有匹配的字段 這個類似于 /xxx/xxx?p={} 匹配這個p String oldParamsJson = httpUrlurl.queryParameter(Constants.PARM); if (oldParamsJson != null) { //因為有的是沒有這個p={"page":0} 而是直接/xxx/index的 HashMap<String, Object> p = mGson.fromJson(oldParamsJson, HashMap.class); //原始參數 if (p != null) { for (Map.Entry<String, Object> entry : p.entrySet()) { rootMap.put(entry.getKey(), entry.getValue()); } } } } else { rootMap.put(key, httpUrlurl.queryParameter(key)); } } //String oldParamJson = httpUrlurl.queryParameter(Constants.PARM);// if (oldParamJson != null) {//// } //把原來請求的和公共的參數進行組裝 rootMap.put("publicParams", commomParamsMap); //重新組裝 String newJsonParams = mGson.toJson(rootMap); //裝換成json字符串 String url = httpUrlurl.toString(); int index = url.indexOf("?"); if (index > 0) { url = url.substring(0, index); } url = url + "?" + Constants.PARM + "=" + newJsonParams; //拼接新的url request = request.newBuilder().url(url).build(); //重新構建請求 //post請求的封裝 } else if (method.equals("POST")) {// FormBody.Builder builder = new FormBody.Builder();// builder.addEncoded("phone","phone"); RequestBody requestBody = request.body(); HashMap<String, Object> rootMap = new HashMap<>(); if (requestBody instanceof FormBody) { for (int i = 0; i < ((FormBody) requestBody).size(); i++) { rootMap.put(((FormBody) requestBody).encodedName(i), ((FormBody) requestBody).encodedValue(i)); } } else { //buffer流 Buffer buffer = new Buffer(); requestBody.writeTo(buffer); String oldParamsJson = buffer.readUtf8(); rootMap = mGson.fromJson(oldParamsJson, HashMap.class); //原始參數 rootMap.put("publicParams", commomParamsMap); //重新組裝 String newJsonParams = mGson.toJson(rootMap); //裝換成json字符串 request = request.newBuilder().post(RequestBody.create(JSON, newJsonParams)).build(); } } } catch (JsonSyntaxException e) { e.printStackTrace(); } //最后通過chain.proceed(request)進行返回 return chain.proceed(request); }

第二步

當我們把自定義的Interceptor構建完成之后,我們需要在Okhttp中進行使用。

return new OkHttpClient.Builder() //HeadInterceptor 實現了Intercepter 用來網Request Header添加一些相關數據 如APP版本 token信息// .addInterceptor(new HttpLoggingInterceptor()) //添加自定義的攔截器,完成公共參數的封裝 .addInterceptor(new CommonParamsInterceptor(gson,application)) .connectTimeout(10, TimeUnit.SECONDS)//鏈接超時 .readTimeout(10, TimeUnit.SECONDS)//設置讀取超時 .build();

這個時候就可以了,我們來看下攔截之前和加入攔截器之后的請求url,看看是否起到了作用。 這個時候我們debug一下看下就明白了。 我們可以看到下圖中上面的參數是只有一個,但是第二行就已經改變了,添加過了我們需要的公共參數,并且還有我們請求的參數。符合我們的要求。

參考文章

Okhttp-wiki 之 Interceptors 攔截器 Okhttp-wiki之Interceptors


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 合川市| 阿荣旗| 保靖县| 达州市| 洞口县| 呼伦贝尔市| 长泰县| 抚州市| 昌江| 乐至县| 桂平市| 黄大仙区| 随州市| 潼南县| 博客| 密云县| 江津市| 金湖县| 大名县| 霍州市| 张掖市| 新疆| 澄城县| 成武县| 山丹县| 措美县| 顺平县| 团风县| 师宗县| 昌图县| 东莞市| 仲巴县| 伊宁市| 沙雅县| 雅江县| 建阳市| 丰城市| 武鸣县| 屏边| 和林格尔县| 南部县|