Retrofit之請(qǐng)求參數(shù)

在上文吩抓,我們了解了如何定義請(qǐng)求Url朵纷,感興趣的朋友可以參見(jiàn)《Retrofit之請(qǐng)求Url》传趾。Retrofit系列持續(xù)更新,本文介紹如何使用Retrofit定義請(qǐng)求參數(shù)负蚊。

請(qǐng)求參數(shù)從傳遞方式可分三種:url參數(shù)神妹,請(qǐng)求主體以及表單編碼。我們來(lái)一一討論家妆。

url參數(shù)

單個(gè)請(qǐng)求參數(shù)

url參數(shù)就是在url鏈接后面的鍵值對(duì)鸵荠,例如https://api.weibo.com/2//statuses/public_timeline.json?access_token=xxx中,access_token就是url參數(shù)伤极,xxx為其值腰鬼。

Retrofit定義url參數(shù)非常直接,只要在方法參數(shù)前面添加@Query("key")注解即可塑荒。@Query中key的值與url中的參數(shù)名稱是一致的熄赡,Retrofit會(huì)自動(dòng)添加這些參數(shù)到url中。

以之前獲取微博公共動(dòng)態(tài)的API為例齿税,具體API詳見(jiàn)http://open.weibo.com/wiki/2/statuses/public_timeline彼硫。從接口中看到,必選參數(shù)只有access_token一個(gè)凌箕,我們定義個(gè)方法如下:

@GET("/statuses/public_timeline.json")
Call<Timeline> timelineForPublic(@Query("access_token") String token);

方法timelineForPublic需要參數(shù)token拧篮,Retrofit會(huì)通過(guò)@Query中定義的名稱access_token將token映射成請(qǐng)求參數(shù)access_token。此時(shí)牵舱,請(qǐng)求url就會(huì)變成:

/statuses/public_timeline.json?access_token=<token>

多個(gè)請(qǐng)求參數(shù)

從獲取微博公共動(dòng)態(tài)的API中我們可以看到串绩,除了必選的access_token,還有三個(gè)可選參數(shù)count芜壁、page以及base_app礁凡,也就是說(shuō)現(xiàn)在請(qǐng)求參數(shù)有四個(gè)了高氮。有了上面定義請(qǐng)求參數(shù)的介紹,我們只需要往方法上添加相應(yīng)的參數(shù)并用@Query進(jìn)行注解:

@GET("/statuses/public_timeline.json")
Call<Timeline> timelineForPublic(@Query("access_token") String token, @Query("count") int count, @Query("page") int page, @Query("base_app") int baseApp);

此時(shí)顷牌,如果我們只需要傳遞access_token剪芍,而不需要其他參數(shù),則可以在調(diào)用方法的時(shí)候傳null窟蓝。當(dāng)然罪裹,我們不能傳null給int這樣的原生類(lèi)型,而需要使用對(duì)應(yīng)的Integer运挫。而Retrofit會(huì)跳過(guò)值為null的參數(shù)状共,并在組裝請(qǐng)求的時(shí)候忽略它們。

獲取公共微博最多有四個(gè)參數(shù)谁帕,那么我們?cè)俨榭聪芦@取好友微博APIhttp://open.weibo.com/wiki/2/statuses/friends_timeline口芍,發(fā)現(xiàn)其有一個(gè)必選參數(shù)以及七個(gè)可選參數(shù),也就是方法會(huì)有八個(gè)參數(shù)雇卷。那么問(wèn)題來(lái)了鬓椭,如果有更多的可選參數(shù),那方法的參數(shù)是不是也會(huì)特別多关划,而且很多時(shí)候我們只需要其中一兩個(gè)請(qǐng)求參數(shù)小染,卻需要提供所有的參數(shù)值,顯然很繁瑣贮折。為了處理這種情況裤翩,QueryMap就該登場(chǎng)了。

我們可以使用下面的方式定義獲取公共微博API的方法:

@GET("/statuses/public_timeline.json")
Call<Timeline> timelineForPublic(@QueryMap Map<String, String> options);

@QueryMap后面需要緊跟著一個(gè)Map< String, String >類(lèi)型调榄,這樣就可以動(dòng)態(tài)地添加查詢參數(shù)了踊赠。如果說(shuō)只需要accept_token參數(shù),則可以像下面這樣調(diào)用:

Map<String, String> options = new HashMap<>();
options.put("access_token", AccessTokenKeeper.readAccessToken(getContext()).getToken());
call = weiboService.timelineForPublic(options);

這樣每庆,我們只需要傳遞我們需要設(shè)置的參數(shù)就可以了筐带。

給每個(gè)請(qǐng)求添加url參數(shù)

在我們查看微博的各個(gè)API時(shí),會(huì)發(fā)現(xiàn)每個(gè)請(qǐng)求都需要一個(gè)access_token參數(shù)缤灵,于是我們就在所有的方法中都添加了對(duì)應(yīng)的參數(shù)伦籍。那么有沒(méi)有簡(jiǎn)單的方式來(lái)給每個(gè)請(qǐng)求都添加相同的參數(shù),從而不需要每個(gè)請(qǐng)求都做相同處理呢腮出?

強(qiáng)大的Retrofit是支持的帖鸦,但是是通過(guò)OkHttp中的攔截器來(lái)實(shí)現(xiàn)的。我們?cè)?a href="http://www.reibang.com/p/511a6266e656" target="_blank">《Retrofit之初體驗(yàn)》提及過(guò)胚嘲,Retrofit直接依賴OkHttp作儿,使用OkHttp作為底層網(wǎng)絡(luò)客戶端。而使用OkHttp可以添加攔截器馋劈,用來(lái)修改即將發(fā)出去的請(qǐng)求攻锰,這個(gè)可以參見(jiàn)《OkHttp之?dāng)r截器》晾嘶。這樣我們就可以在攔截器中,對(duì)每個(gè)請(qǐng)求添加一個(gè)access_token參數(shù)了:

private static OkHttpClient.Builder okHttpClientBuilder =
        new OkHttpClient.Builder().addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();
                HttpUrl originalHttpUrl = originalRequest.url();

                HttpUrl url = originalHttpUrl.newBuilder()
                        .addQueryParameter("access_token", AccessTokenKeeper.readAccessToken(MyApplication.getInstance()).getToken())
                        .build();
                Request request = originalRequest.newBuilder()
                        .url(url)
                        .method(originalRequest.method(), originalRequest.body())
                        .build();

                return chain.proceed(request);
            }
        });

首先獲取到了HttpUrl對(duì)象口注,然后基于原始的HttpUrl對(duì)象創(chuàng)建一個(gè)新的構(gòu)建器,從而可以使用addQueryPatameter()方法添加額外的查詢參數(shù)君珠,最后將這個(gè)新的HttpUrl對(duì)象通過(guò)Request.Builder方法設(shè)置到Request中寝志。

請(qǐng)求主體

在我們實(shí)際應(yīng)用中,大多數(shù)時(shí)候會(huì)通過(guò)請(qǐng)求主體向服務(wù)器發(fā)送數(shù)據(jù)策添。以我們的慣例材部,都會(huì)以微博API為例,但可惜的是并沒(méi)有找過(guò)微博使用這種方式的API唯竹,而都使用的是表單方式乐导,這個(gè)會(huì)在后面討論。所以個(gè)很常見(jiàn)的例子浸颓,那就是登陸物臂,通常請(qǐng)求參數(shù)如下:

{
    "username":"xxx",
    "password":"xxx"
}

好的,登錄的方法定義如下:

@POST("login-path")
Call<User> login(@Body LoginParam param);

其中LoginParam.java類(lèi)如下:

public class LoginParam {
    private String username;
    private String password;
    public LoginParam(String username, String password) { 
        this.username = username;
        this.password = password;
    }
}

首先产上,我們使用了@Body注解了方法參數(shù)棵磷,而我們?cè)趧?chuàng)建Retrofit.Builder的時(shí)候也為其添加了GsonConverter轉(zhuǎn)換器。

new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create());

這樣晋涣,Retrofit會(huì)將LoginParam對(duì)象轉(zhuǎn)換為Json仪媒,并將其作為主體數(shù)據(jù)添加到請(qǐng)求中,支持了使用請(qǐng)求主體向服務(wù)器發(fā)送數(shù)據(jù)谢鹊。

表單

在上面我們使用了用請(qǐng)求主體的方式來(lái)向服務(wù)器發(fā)送數(shù)據(jù)算吩,除了這種方式,還可以通過(guò)表單編碼(form-urlencoded)的形式佃扼。微博API中的寫(xiě)入接口都是采用這種方式向服務(wù)器發(fā)送數(shù)據(jù)的偎巢,我們這里以轉(zhuǎn)發(fā)微博為例,具體API詳見(jiàn)http://open.weibo.com/wiki/2/statuses/repost兼耀。

首先艘狭,定義轉(zhuǎn)發(fā)微博的方法:

@FormUrlEncoded
@POST("statuses/repost.json")
Call<WeiboTimeline> repost(@Field("id") String id);

我們看到了@FormUrlEncoded注解,這個(gè)注解不能使用在GET請(qǐng)求上翠订,因?yàn)樗硪敕?wù)器發(fā)送數(shù)據(jù)巢音。此外,在參數(shù)id上使用@Field注解尽超,表示請(qǐng)求會(huì)發(fā)送此參數(shù)到服務(wù)器官撼,而@Field("id")中的id則定義的是參數(shù)名稱。

與@Query類(lèi)似似谁,當(dāng)你有多個(gè)參數(shù)要發(fā)送時(shí)傲绣,只需要使用@Field注解它們即可掠哥。同樣與@QueryMap對(duì)應(yīng)的有個(gè)@FieldMap注解,具體使用類(lèi)似秃诵。

@Field與@FieldMap都有一個(gè)屬性encoded续搀,表示鍵值對(duì)是否進(jìn)行url編碼,默認(rèn)為false菠净。以@Field為例禁舷,使用如下:

@FormUrlEncoded
@POST("statuses/repost.json")
Call<WeiboTimeline> repost(@Field(value="id", encoded=true) String id);

了解完@Field之后,我們討論下表單編碼與url參數(shù)的區(qū)別:表單編碼使用在POST請(qǐng)求中的毅往,而url參數(shù)是用在GET請(qǐng)求中的牵咙。表單編碼使用請(qǐng)求主體發(fā)送數(shù)據(jù)到服務(wù)器,而不是url參數(shù)攀唯。而url參數(shù)的使用主要是為了從服務(wù)器過(guò)濾或者獲取指定的數(shù)據(jù)洁桌。

Ok,本文就討論到這里侯嘀,感謝大家的閱讀另凌,下文我們將討論Retrofit如何定義請(qǐng)求頭。

如果你對(duì)retrofit感興趣戒幔,同時(shí)你也覺(jué)得我的文章可以給你帶來(lái)那么一丟丟的幫助途茫,敬請(qǐng)關(guān)注,后續(xù)會(huì)繼續(xù)介紹Retrofit的相關(guān)使用溪食。

源碼地址:
https://github.com/FILWAndroid/DevJourney

關(guān)于源碼:

  1. 不只是本文涉及的代碼囊卜,會(huì)包含很多知識(shí)點(diǎn)的代碼,應(yīng)該都會(huì)在我的簡(jiǎn)書(shū)中進(jìn)行介紹错沃。
  2. 有可能代碼與本文中所貼出來(lái)的有差異栅组,但應(yīng)該都是我覺(jué)得更好的方式吧。
  3. 新浪微博相關(guān)的代碼運(yùn)行顯示不出來(lái)結(jié)果枢析,感興趣的可以參考新浪微博SDK玉掸,配置工程。
  4. 歡迎大家對(duì)我進(jìn)行批評(píng)教育醒叁。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末司浪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子把沼,更是在濱河造成了極大的恐慌啊易,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饮睬,死亡現(xiàn)場(chǎng)離奇詭異租谈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)捆愁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)割去,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)窟却,“玉大人,你說(shuō)我怎么就攤上這事呻逆】浜眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵咖城,是天一觀的道長(zhǎng)茬腿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)酒繁,這世上最難降的妖魔是什么滓彰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任控妻,我火速辦了婚禮州袒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弓候。我一直安慰自己郎哭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布菇存。 她就那樣靜靜地躺著夸研,像睡著了一般。 火紅的嫁衣襯著肌膚如雪依鸥。 梳的紋絲不亂的頭發(fā)上亥至,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音贱迟,去河邊找鬼姐扮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛衣吠,可吹牛的內(nèi)容都是我干的茶敏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缚俏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惊搏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起忧换,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恬惯,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后亚茬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宿崭,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年才写,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葡兑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奖蔓。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖讹堤,靈堂內(nèi)的尸體忽然破棺而出吆鹤,到底是詐尸還是另有隱情,我是刑警寧澤洲守,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布疑务,位于F島的核電站,受9級(jí)特大地震影響梗醇,放射性物質(zhì)發(fā)生泄漏知允。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一叙谨、第九天 我趴在偏房一處隱蔽的房頂上張望温鸽。 院中可真熱鬧,春花似錦手负、人聲如沸涤垫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蝠猬。三九已至,卻和暖如春统捶,著一層夾襖步出監(jiān)牢的瞬間榆芦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工喘鸟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匆绣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓迷守,卻偏偏與公主長(zhǎng)得像犬绒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兑凿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,074評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理凯力,服務(wù)發(fā)現(xiàn),斷路器礼华,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 整體Retrofit內(nèi)容如下: 1咐鹤、Retrofit解析1之前哨站——理解RESTful2、Retrofit解析2...
    隔壁老李頭閱讀 15,075評(píng)論 4 39
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,803評(píng)論 6 342
  • “中國(guó)人混的就是圈子捧请》采” 一個(gè)在圈子里小有成就后自己開(kāi)始創(chuàng)業(yè),目前已融資千萬(wàn)的Boss對(duì)兩個(gè)職場(chǎng)小白這樣說(shuō)道疹蛉。 引...
    皮皮七閱讀 712評(píng)論 2 1