添加依賴 https://github.com/square/retrofit
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
如何使用
- 注一:Retrofit2 的baseUlr 必須以 /(斜線) 結(jié)束,不然會拋出一個IllegalArgumentException,所以如果你看到別的教程沒有以 / 結(jié)束,那么多半是直接從Retrofit 1.X 照搬過來的。
- 注二:上面的 注1 應(yīng)該描述為 baseUrl 中的路徑(path)必須以 / 結(jié)束, 因為有些特殊情況可以不以/結(jié)尾,比如 其實這個 URL https://www.baidu.com?key=value用來作為baseUrl其實是可行的,因為這個URL隱含的路徑就是 /(斜線,代表根目錄) ,而后面的?key=value在拼裝請求時會被丟掉所以寫上也沒用。之所以 Retrofit 2 在文檔上要求必須以 /(斜線) 結(jié)尾的要求想必是要消除歧義以及簡化規(guī)則。
- 接口定義 以獲取指定id的Blog為例:
public interface BlogService {
@GET("blog/{id}")
Call<ResponseBody> getBlog(@Path("id") int id);
}
注意,這里是interface不是class,所以我們是無法直接調(diào)用該方法,我們需要用Retrofit創(chuàng)建一個BlogService的代理對象。
- 接口調(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中注解的使用十分廣泛,沒了解過的可以先湊活看看
第一類:HTTP請求方法
以上表格中的除HTTP以外都對應(yīng)了HTTP標(biāo)準(zhǔn)中的請求方法,而HTTP注解則可以代替以上方法中的任意一個注解,有3個屬性:method、path,hasBody
public interface BlogService {
/**
* method 表示請求的方法,區(qū)分大小寫
* path表示路徑
* hasBody表示是否有請求體
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getBlog(@Path("id") int id);
}
第二類:標(biāo)記類
第三類:參數(shù)類
方法參數(shù)這部分也很多,為了方便理解和記憶,有些可以看成是相同的,像 @Field 和 @FieldMap,@Query 和 @QueryMap,@Part 和 @PartMap,@Headers 和 @Header(這兩個和前面三對還有些區(qū)別)。
- @Path(GET請求)
@GET("api/{Country}")
Call<List<Province>> getProvinces(@Path("Country") String country);
通過 Path 注解,可以將 GET 中{Country}部分進(jìn)行動態(tài)替換,這個很好理解。
- @Url(GET請求)
用于替換url中某個字段,例如:
@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請求)
如,我要訪問下面這個URL,在 ?之后是查詢參數(shù),這些參數(shù)就可以通過 @Query 來動態(tài)設(shè)定。
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world
查詢參數(shù)分解為鍵值對:
key——–value
a————-fy
f————auto
t————auto
w———hello%20world
使用 @Query 對每一個鍵值對進(jìn)行參數(shù)設(shè)置,當(dāng)有多個鍵值對時,就可以通過 @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)建接口實例的方法,重點看下面的代碼
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ū)別在于 @Header 用于不固定的請求頭,@Headers 用于添加固定請求頭,關(guān)于請求頭的概念,需要去了解下消息結(jié)構(gòu)的 header 部分。
@Headers 設(shè)置請求頭的Content-type,即設(shè)置編碼格式,固定請求頭 意思是使用這個請求接口的編碼格式都是一樣的。
public interface HeaderService {
@POST("api/users")
Call<ResponseInfo> uploadUser(@Header("Content-Type") String contentType,@Field("username") String username);
}
@Header 設(shè)定動態(tài)設(shè)置請求頭編碼格式,在調(diào)用方式,通過參數(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)換為我們想要的類型,
有了Converter之后我們就可以寫把我們的第一個例子的接口寫成這個樣子了:
public interface BlogService {
@GET("blog/{id}")
Call<Result<Blog>> getBlog(@Path("id") int id);
}
當(dāng)然只改變泛型的類型是不行的,我們在創(chuàng)建Retrofit時需要明確告知用于將ResponseBody轉(zhuǎn)換我們泛型中的類型時需要使用的Converter,引入Gson支持:
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
通過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é)合更香哦
具體的實現(xiàn)這里就不講了,但retrofit2 + RxJava2是十分常見的網(wǎng)絡(luò)請求實現(xiàn)方式哦