
image.png
前言
- 在之前一篇文章中,我給大家介紹了Retrofit+RxJava搭建網(wǎng)絡(luò)請(qǐng)求,并進(jìn)行了簡(jiǎn)單的封裝(沒看過的童鞋可以點(diǎn)這里的鏈接跳轉(zhuǎn) Android中用Retrofit+Rxjava搭建網(wǎng)絡(luò)請(qǐng)求 )。但是,如果你認(rèn)為這樣就足夠了的話,那么你就錯(cuò)了,要想在項(xiàng)目中使用好Retrofit,還有很多地方需要學(xué)習(xí)的。
動(dòng)態(tài)Url
- 在之前的示例中大家可能已經(jīng)發(fā)現(xiàn),使用Retrofit定義接口的時(shí)候,請(qǐng)求url是在@GET、@POST注解后面的:
public interface RXApi{
@GET("/url")
Call<T> doSomething();
}
- 但是,在我們的實(shí)際項(xiàng)目中不可能所有接口url都是固定的,在筆者的項(xiàng)目中就有這種需求,要根據(jù)服務(wù)器返回的url來獲取相關(guān)數(shù)據(jù),在這個(gè)時(shí)候,使用上面的方式無疑是不可能的。在這個(gè)時(shí)候,我們就要用到Retrfit提供的一個(gè)@Url借口,這樣就能動(dòng)態(tài)的設(shè)置url:
public interface RXApi{
@GET // 在使用@Url注解時(shí),@GET、@POST注解之后是沒有url參數(shù)的
Call<T> doSomething(@Url String url); // Retrofit會(huì)請(qǐng)求這里的url
}
- 在封裝Retrofit的時(shí)候,我們?cè)O(shè)置了baseUrl,在請(qǐng)求網(wǎng)絡(luò)的時(shí)候,@GET注解后面的url會(huì)拼接到baseUrl后面,但是,如果我們請(qǐng)求的url地址和baseUrl不同呢?這里就要說到Retrofit請(qǐng)求url的使用了。
- 在配置baseUrl的時(shí)候,url都是以 "https://" 或者 "http://" 作為開頭的,那么在定義接口的時(shí)候,或者使用動(dòng)態(tài)url的時(shí)候,如果url有scheme 即以"https://" 或者 "http://" 作為開頭,那么就會(huì)以設(shè)置的參數(shù)作為地址請(qǐng)求數(shù)據(jù),否則,會(huì)將參數(shù)拼接到baseUrl后作為地址請(qǐng)求數(shù)據(jù):
public interface RXApi{
/* baseUrl = "http://www.baidu.com/" */
@GET("tieba") // 這里請(qǐng)求的地址是:http://www.baidu.com/tieba
Call<T> getData();
@GET("http://www.qq.com") // 這里請(qǐng)求的地址是:http://www.qq.com
Call<T> getData();
}
- 使用動(dòng)態(tài)url的時(shí)候也遵循同樣的規(guī)律
中文亂碼
- 雖然說,現(xiàn)在的項(xiàng)目都是使用UTF-8的編碼格式,但是,在使用Retrofit的過程中,筆者發(fā)現(xiàn)有時(shí)候還是會(huì)出現(xiàn)中文亂碼的問題,那么這個(gè)時(shí)候就要用到@FormUrlEncoded注解了:
public interface RXApi{
@FormUrlEncoded // 在方法前使用注解
@POST("url") // 有中文,當(dāng)然使用@POST啦
Call<T> getData(@Query("var1") String var1, // 正常的@Query還是可以使用
@Field("var2") String var2, // 需要防止亂碼的參數(shù)使用@Field注解
@FieldMap Map<T, T> map // 如果有多個(gè)數(shù)據(jù),可以使用@FieldMap注解
);
}
- 注意:如果使用了@FormUrlEncoded注解,那么在方法的參數(shù)中至少要有一個(gè)@Field或@FieldMap注解。
文件上傳
- 文件上傳,不用說,在實(shí)際項(xiàng)目中是肯定會(huì)用到的,那么使用Retrofit怎么實(shí)現(xiàn)呢?Retrofit給我們提供了一個(gè)@Multipart注解用于解決這個(gè)問題:
public interface RXApi{
@Multipart // 方法前使用注解
@GET("url")
Call<T> upload(@Part("file\"; filename=\"tmpicon.jpg\"") RequestBody body); // 上傳固定名稱文件,tmpicon.jpg為文件名
@Multipart
@GET("url")
Call<T> uploads(@Part MultipartBody.Part bodys); // 上傳不固定名稱文件
}
- 接口調(diào)用:
// 創(chuàng)建RequestBody對(duì)象
// file 文件對(duì)象
// MediaType.parse("multipart/form-data") 以表單類型提交
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
// 創(chuàng)建MultipartBody.Part對(duì)象
// name 參數(shù)名稱
// fileName 文件名稱
// requestBody RequestBody對(duì)象
MultipartBody.Part part = MultipartBody.Part.createFormData(name, fileName, requestBody);
// 上傳
upload(requestBody);
uploads(part);
- 如果你需要上傳多個(gè)文件的話,Retrofit也提供了@PartMap注解,用法和@FieldMap類似。
文件下載
- 既然有上傳,那么肯定有下載的啦,Retrofit下載文件也是比較簡(jiǎn)單的:
public interface RXApi{
@GET // 下載文件,一般應(yīng)該很少使用固定url的吧、、、
Call<ResponseBody> download(@Url String url); // 筆者項(xiàng)目中使用,測(cè)試了很多都有問題,使用ResponseBody成功
}
- 調(diào)用接口就不說了,請(qǐng)求成功后,返回的數(shù)據(jù)是ResponseBody,可以調(diào)用body()方法獲取返回?cái)?shù)據(jù),寫入到文件中。
- 注意:這種方法只能用于下載小文件,大文件是不行滴。而且Retrofit并沒有為我們提供下載進(jìn)度監(jiān)聽,所以無法獲取到下載進(jìn)度,當(dāng)然了,這些問題都是有解決方案的。咱們下次再聊。