添加依賴 https://github.com/square/retrofit
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
如何使用
- 注一:Retrofit2 的baseUlr 必須以 /(斜線) 結(jié)束渐裸,不然會(huì)拋出一個(gè)IllegalArgumentException,所以如果你看到別的教程沒(méi)有以 / 結(jié)束昏鹃,那么多半是直接從Retrofit 1.X 照搬過(guò)來(lái)的。
- 注二:上面的 注1 應(yīng)該描述為 baseUrl 中的路徑(path)必須以 / 結(jié)束洞渤, 因?yàn)橛行┨厥馇闆r可以不以/結(jié)尾属瓣,比如 其實(shí)這個(gè) URL https://www.baidu.com?key=value用來(lái)作為baseUrl其實(shí)是可行的,因?yàn)檫@個(gè)URL隱含的路徑就是 /(斜線护昧,代表根目錄) 粗截,而后面的?key=value在拼裝請(qǐng)求時(shí)會(huì)被丟掉所以寫(xiě)上也沒(méi)用。之所以 Retrofit 2 在文檔上要求必須以 /(斜線) 結(jié)尾的要求想必是要消除歧義以及簡(jiǎn)化規(guī)則熊昌。
- 接口定義 以獲取指定id的Blog為例:
public interface BlogService {
@GET("blog/{id}")
Call<ResponseBody> getBlog(@Path("id") int id);
}
注意,這里是interface不是class灭美,所以我們是無(wú)法直接調(diào)用該方法,我們需要用Retrofit創(chuàng)建一個(gè)BlogService的代理對(duì)象昂利。
- 接口調(diào)用
Call<ResponseBody> call = service.getBlog(2);
// 用法和OkHttp的call如出一轍,
// 不同的是如果是Android系統(tǒng)回調(diào)方法執(zhí)行在主線程
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
Retrofit注解詳解
Android中注解的使用十分廣泛页眯,沒(méi)了解過(guò)的可以先湊活看看
第一類(lèi):HTTP請(qǐng)求方法
以上表格中的除HTTP以外都對(duì)應(yīng)了HTTP標(biāo)準(zhǔn)中的請(qǐng)求方法,而HTTP注解則可以代替以上方法中的任意一個(gè)注解,有3個(gè)屬性:method、path,hasBody
public interface BlogService {
/**
* method 表示請(qǐng)求的方法襟铭,區(qū)分大小寫(xiě)
* path表示路徑
* hasBody表示是否有請(qǐng)求體
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getBlog(@Path("id") int id);
}
第二類(lèi):標(biāo)記類(lèi)
第三類(lèi):參數(shù)類(lèi)
方法參數(shù)這部分也很多短曾,為了方便理解和記憶赐劣,有些可以看成是相同的,像 @Field 和 @FieldMap魁兼,@Query 和 @QueryMap,@Part 和 @PartMap盖呼,@Headers 和 @Header(這兩個(gè)和前面三對(duì)還有些區(qū)別)化撕。
- @Path(GET請(qǐng)求)
@GET("api/{Country}")
Call<List<Province>> getProvinces(@Path("Country") String country);
通過(guò) Path 注解,可以將 GET 中{Country}部分進(jìn)行動(dòng)態(tài)替換蟹瘾,這個(gè)很好理解。
- @Url(GET請(qǐng)求)
用于替換url中某個(gè)字段憾朴,例如:
@GET("group/{id}/users")
Call<Book> groupList(@Path("id") int groupId);
@Url 注解同樣可設(shè)置 URL众雷,達(dá)到上面 GET 后面設(shè)置的效果。
@GET
Call<List<Province>> getProvinces(@Url String url);
- @Query 和 @QueryMap(GET請(qǐng)求)
如报腔,我要訪問(wèn)下面這個(gè)URL剖淀,在 纯蛾?之后是查詢參數(shù)翻诉,這些參數(shù)就可以通過(guò) @Query 來(lái)動(dòng)態(tài)設(shè)定捌刮。
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
查詢參數(shù)分解為鍵值對(duì):
key——–value
a————-fy
f————auto
t————auto
w———hello%20world
使用 @Query 對(duì)每一個(gè)鍵值對(duì)進(jìn)行參數(shù)設(shè)置,當(dāng)有多個(gè)鍵值對(duì)時(shí)绅作,就可以通過(guò) @QueryMap
public interface QueryService {
//baseurl 為http://fy.iciba.com/
@GET("ajax.php")
Call<Message> getMessage(@Query("a") String param1,
@Query("f") String param2, @Query("t") String param3,
@Query("w") String param4);
@GET("{message}")
Call<Message> getMessage(@QueryMap Map<String, String> params);
}
使用
//getService 創(chuàng)建接口實(shí)例的方法,重點(diǎn)看下面的代碼
QueryService getService = (QueryService) getService("http://fy.iciba.com/", GetService.class);
/**
* url
* http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
*/
//@Query
Call<Message> call = getService.getMessage("fy","auto","auto","hello%20world");
//@QueryMap
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put("a", "fy");
paramsMap.put("f", "auto");
paramsMap.put("t", "auto");
paramsMap.put("w", "hello%20world");
Call<Message> call = getService.getMessage(paramsMap);
- @Header 和 @Headers(POST請(qǐng)求)
這兩個(gè)注解都是作用于請(qǐng)求頭个少,區(qū)別在于 @Header 用于不固定的請(qǐng)求頭,@Headers 用于添加固定請(qǐng)求頭夜焦,關(guān)于請(qǐng)求頭的概念,需要去了解下消息結(jié)構(gòu)的 header 部分茫经。
@Headers 設(shè)置請(qǐng)求頭的Content-type,即設(shè)置編碼格式抹镊,固定請(qǐng)求頭 意思是使用這個(gè)請(qǐng)求接口的編碼格式都是一樣的瞪慧。
public interface HeaderService {
@POST("api/users")
Call<ResponseInfo> uploadUser(@Header("Content-Type") String contentType,@Field("username") String username);
}
@Header 設(shè)定動(dòng)態(tài)設(shè)置請(qǐng)求頭編碼格式,在調(diào)用方式氨菇,通過(guò)參數(shù)傳遞
public interface HeaderService {
@POST("api/users")
Call<ResponseInfo> uploadUser(@Header("Content-Type") String contentType,@Field("username") String username);
}
調(diào)用
Call call = service.uploadNewUser(“application/x-www-form-urlencoded;charset=UTF-8”,”Ralf”);
Gson與Converter
在默認(rèn)情況下Retrofit只支持將HTTP的響應(yīng)體轉(zhuǎn)換換為ResponseBody,而Converter就是Retrofit為我們提供用于將ResponseBody轉(zhuǎn)換為我們想要的類(lèi)型妓湘,
有了Converter之后我們就可以寫(xiě)把我們的第一個(gè)例子的接口寫(xiě)成這個(gè)樣子了:
public interface BlogService {
@GET("blog/{id}")
Call<Result<Blog>> getBlog(@Path("id") int id);
}
當(dāng)然只改變泛型的類(lèi)型是不行的查蓉,我們?cè)趧?chuàng)建Retrofit時(shí)需要明確告知用于將ResponseBody轉(zhuǎn)換我們泛型中的類(lèi)型時(shí)需要使用的Converter,引入Gson支持:
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
通過(guò)GsonConverterFactory為Retrofit添加Gson支持:
Gson gson = new GsonBuilder()
//配置你的Gson
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
//可以接收自定義的Gson,當(dāng)然也可以不傳
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
retrofit2 + RxJava2結(jié)合更香哦
具體的實(shí)現(xiàn)這里就不講了榜贴,但retrofit2 + RxJava2是十分常見(jiàn)的網(wǎng)絡(luò)請(qǐng)求實(shí)現(xiàn)方式哦