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

首頁 > 系統 > Android > 正文

為Retrofit統一添加post請求的默認參數的方法

2019-10-22 18:13:19
字體:
來源:轉載
供稿:網友

最近在學習使用Retrofit,并嘗試將之引入到現有的項目中來。大家都知道,在Http請求中我們使用 Content-Type 來指定不同格式的請求信息:

APP_FORM_URLENCODED("application/x-www-form-urlencoded"), APP_JSON("application/json"), APP_OCTET_STREAM("application/octet-stream"), MULTIPART_FORM_DATA("multipart/form-data"), TEXT_HTML("text/html"), TEXT_PLAIN("text/plain"),

實際項目中通常最后的請求參數都包含默認的一些參數(Token,Api版本、App版本等)和普通的請求參數。網上有很多關于第一種 Content-Type 添加默認參數的方法。而在我現有項目上,除文件上傳外絕大多數請求都走了 post + application/json 的方式。這里暫不討論兩者的優缺點,而是談下 Content-Type 為 application/json 時,如何添加默認參數。

傳統方式:

我們先來回憶下兩種方式

public interface Apis {  @POST("user/login") Observable<Entity<User>> login(@Body RequestBody body);//構造一個RequestBody對象  @POST("user/login") Observable<Entity<User>> login(@Body LoginInfo loginInfo);//構造一個實體對象  }

第二種方法,你需要為每一個請求的對象創建一個不同的Model,太麻煩了,這里選擇第一種直接構造RequestBody對象:

Retrofit mRetrofit = new Retrofit.Builder()    .baseUrl(HttpConfig.BASE_URL)    .addConverterFactory(GsonConverterFactory.create())//添加gson轉換器    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava轉換器    .client(new OkHttpClient.Builder().build())    .build();Apis mAPIFunction = mRetrofit.create(Apis.class);Map<String, Object> params = new LinkedHashMap<>(); params.put("name", "吳彥祖"); params.put("request", "123456");RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JsonHelper.toJSONString(params));mAPIFunction.login(RequestBody.create(requestBody))

執行后通過抓包查看,請求體如下:

Retrofit,post請求,參數,post請求參數

而我希望的結果是這樣的:

Retrofit,post請求,參數,post請求參數

當然我們可以每次構造 RequestBody,在傳入的參數中加入默認參數:

public static RequestBody getRequestBody(HashMap<String, Object> hashMap) {  Map<String, Object> params = new LinkedHashMap<>();  params.put("auth", getBaseParams());  params.put("request", hashMap);  return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JsonHelper.toJSONString(params)); }

這樣完全沒問題,但不夠優雅,所以接下來我們來討論我所想到的一種方式

攔截器方式:

哈哈,相信熟悉OkHttp的同學已經想到這種方式了,是的很多網上關于第一種 Content-Type 添加默認參數也是這么做的(原文鏈接):

@Override public Response intercept(Chain chain) throws IOException {  Request request = chain.request();  if (request.method().equals("POST")) {  if (request.body() instanceof FormBody) {   FormBody.Builder bodyBuilder = new FormBody.Builder();   FormBody formBody = (FormBody) request.body();   //把原來的參數添加到新的構造器,(因為沒找到直接添加,所以就new新的)   for (int i = 0; i < formBody.size(); i++) {    bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));   }   formBody = bodyBuilder     .addEncoded("clienttype", "1")     .addEncoded("imei", "imei")     .addEncoded("version", "VersionName")     .addEncoded("timestamp", String.valueOf(System.currentTimeMillis()))     .build();   request = request.newBuilder().post(formBody).build();  }   return chain.proceed(request);  }

在上面,我們拿到了request對象,然后拿到了requestBody對象,然后 判斷是不是FormBody類型,如果是的話,將里面的鍵值對取出,并添加默認參數的鍵值對并構造出一個新的formBody對象,最后將原來用request對象構造出新的一個request對象,將新的formBody對象穿進去,攔截器返回。formBody對象是 Content-Type 為 application/x-www-form-urlencoded 時,Retrofit為我們生成的對象,它是RequestBody的子類;而 Content-Type 為 application/json 時,生成的就是 RequestBody (準確的說是匿名子類)。所以我們只要繼承重寫 RequestBody ,記錄請求內容,再將它在攔截器里取出加入并處理就行了。

public class PostJsonBody extends RequestBody { private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static final Charset charset = Util.UTF_8; private String content; public PostJsonBody(@NonNull String content) {  this.content = content; } public String getContent() {  return content; } @Nullable @Override public MediaType contentType() {  return JSON; } @Override public void writeTo(@NonNull BufferedSink sink) throws IOException {  byte[] bytes = content.getBytes(charset);  if (bytes == null) throw new NullPointerException("content == null");  Util.checkOffsetAndCount(bytes.length, 0, bytes.length);  sink.write(bytes, 0, bytes.length); } public static RequestBody create(@NonNull String content) {  return new PostJsonBody(content); }}

攔截器里面取出原始json數據,并添加新的默認參數:

@Override public Response intercept(@NonNull Chain chain) throws IOException {  Request originalRequest = chain.request();  Request.Builder builder = originalRequest.newBuilder();  if (originalRequest.method().equals("POST")) {   RequestBody requestBody = originalRequest.body();   if (requestBody instanceof PostJsonBody) {    String content = ((PostJsonBody) requestBody).getContent();    HashMap<String, Object> hashMap = JsonHelper.fromJson(content, HashMap.class);    builder.post(RequestBodyFactory.getRequestBody(hashMap));   }  }  return chain.proceed(builder.build()); }

這樣在外面我們只要改動一行代碼就可以實現全局添加默認參數:

RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"),JsonHelper.toJSONString(params));

替換為:

 

復制代碼 代碼如下:
RequestBody requestBody = PostJsonBody.create( JsonHelper.toJSONString(params));

 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阿拉善右旗| 乌拉特前旗| 襄汾县| 云浮市| 霍邱县| 建平县| 锦州市| 沂源县| 广西| 宜宾市| 鹤庆县| 溧阳市| 鄯善县| 个旧市| 综艺| 潞西市| 昌平区| 郯城县| 绥芬河市| 凌云县| 秦皇岛市| 铜川市| 舞钢市| 元阳县| 姜堰市| 阳信县| 济源市| 古浪县| 茂名市| 印江| 盐城市| 信阳市| 汝州市| 高雄市| 湖南省| 宜州市| 墨脱县| 牟定县| 荆门市| 英吉沙县| 淮北市|