最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

為Retrofit統(tǒng)一添加post請求的默認(rèn)參數(shù)的方法

 更新時間:2018年04月02日 10:11:13   作者:大頭呆  
這篇文章主要介紹了為Retrofit統(tǒng)一添加post請求的默認(rèn)參數(shù)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

最近在學(xué)習(xí)使用Retrofit,并嘗試將之引入到現(xiàn)有的項目中來。大家都知道,在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"),

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

傳統(tǒng)方式:

我們先來回憶下兩種方式

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

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

Retrofit mRetrofit = new Retrofit.Builder()
    .baseUrl(HttpConfig.BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())//添加gson轉(zhuǎn)換器
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava轉(zhuǎn)換器
    .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))

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

而我希望的結(jié)果是這樣的:

當(dāng)然我們可以每次構(gòu)造 RequestBody,在傳入的參數(shù)中加入默認(rèn)參數(shù):

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));
 }

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

攔截器方式:

哈哈,相信熟悉OkHttp的同學(xué)已經(jīng)想到這種方式了,是的很多網(wǎng)上關(guān)于第一種 Content-Type 添加默認(rèn)參數(shù)也是這么做的(原文鏈接):

@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();
   //把原來的參數(shù)添加到新的構(gòu)造器,(因為沒找到直接添加,所以就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類型,如果是的話,將里面的鍵值對取出,并添加默認(rèn)參數(shù)的鍵值對并構(gòu)造出一個新的formBody對象,最后將原來用request對象構(gòu)造出新的一個request對象,將新的formBody對象穿進(jìn)去,攔截器返回。formBody對象是 Content-Type 為 application/x-www-form-urlencoded 時,Retrofit為我們生成的對象,它是RequestBody的子類;而 Content-Type 為 application/json 時,生成的就是 RequestBody (準(zhǔn)確的說是匿名子類)。所以我們只要繼承重寫 RequestBody ,記錄請求內(nèi)容,再將它在攔截器里取出加入并處理就行了。

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數(shù)據(jù),并添加新的默認(rèn)參數(shù):

@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());
 }

這樣在外面我們只要改動一行代碼就可以實現(xiàn)全局添加默認(rèn)參數(shù):

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

替換為:

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android中使用socket通信實現(xiàn)消息推送的方法詳解

    Android中使用socket通信實現(xiàn)消息推送的方法詳解

    這篇文章主要介紹了Android中使用socket通信實現(xiàn)消息推送的方法,文中舉了一個消息發(fā)送端和一個消息接收端以及服務(wù)器端的例子來說明原理并且展示了客戶端的實現(xiàn),需要的朋友可以參考下
    2016-04-04
  • flutter簡單使用案例

    flutter簡單使用案例

    這篇文章主要介紹了使用Flutter短視頻上滑翻頁效果,本篇介紹了?Flutter的翻頁組件PageView的使用,通過?PageView可以輕松實現(xiàn)類似短視頻的縱向上滑翻頁的效果,也可以實現(xiàn)橫向翻頁效果(如閱讀類軟件),需要的朋友可以參考下
    2023-05-05
  • Android 更新RecyclerView的好方法

    Android 更新RecyclerView的好方法

    在使用RecyclerView的時候不免要修改RecyclerView的數(shù)據(jù),使用notifyDataSetChanged()來刷新界面,但是當(dāng)數(shù)據(jù)多,而只是修改了一點的數(shù)據(jù),或者刷新比較頻繁,這樣就會導(dǎo)致界面卡頓,用戶交互特別不好,這時可以使用RecyclerView方法解決,具體實現(xiàn)代碼大家參考下本文吧
    2017-06-06
  • android分享純圖片到QQ空間實現(xiàn)方式

    android分享純圖片到QQ空間實現(xiàn)方式

    今天小編就為大家分享一篇關(guān)于android分享純圖片到QQ空間實現(xiàn)方式,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Android Service中使用Toast無法正常顯示問題的解決方法

    Android Service中使用Toast無法正常顯示問題的解決方法

    這篇文章主要介紹了Android Service中使用Toast無法正常顯示問題的解決方法,分析了Service中Toast無法正常顯示的原因與相關(guān)的解決方法,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-10-10
  • android用PopWindow做下拉框?qū)嵗a

    android用PopWindow做下拉框?qū)嵗a

    本篇文章主要介紹了android用PopWindow做下拉框?qū)嵗a,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01
  • 基于TabLayout中的Tab間隔設(shè)置方法(實例講解)

    基于TabLayout中的Tab間隔設(shè)置方法(實例講解)

    下面小編就為大家分享一篇基于TabLayout中的Tab間隔設(shè)置方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • 詳解Android中motion_toast的使用

    詳解Android中motion_toast的使用

    我們通常會用 toast(也叫吐司)來顯示提示信息,例如網(wǎng)絡(luò)請求錯誤,校驗錯誤等等。本文為大家介紹一個非常有趣的toast組件 —— motion_toast,感興趣的可以了解一下
    2022-06-06
  • onMeasure被執(zhí)行兩次原理解析

    onMeasure被執(zhí)行兩次原理解析

    這篇文章主要為大家介紹了onMeasure被執(zhí)行兩次原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Android中CountDownTimer倒計時器用法實例

    Android中CountDownTimer倒計時器用法實例

    這篇文章主要介紹了Android中CountDownTimer倒計時器用法,以實例形式分析了Android中CountDownTimer類的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10

最新評論

驻马店市| 双牌县| 义乌市| 辽宁省| 桃园县| 万全县| 诸城市| 昌邑市| 穆棱市| 常熟市| 故城县| 长武县| 清水河县| 垣曲县| 屯留县| 沛县| 邯郸县| 白银市| 乌鲁木齐市| 桐乡市| 娄烦县| 广水市| 宣武区| 大冶市| 根河市| 雅安市| 怀安县| 老河口市| 襄樊市| 积石山| 枣庄市| 石嘴山市| 宁阳县| 娄烦县| 平度市| 蓬溪县| 宝山区| 通许县| 祥云县| 潞城市| 柳林县|