Retrofit 是什么?
Retrofit is a type-safe HTTP client for Android and java.
互聯網上的資料很多很雜,在收集資料初步了解后,我先粗糙地認為:Retrofit 適用于與 Web 服務器提供的 API 接口進行通信。
當你想要做更多的 HTTP 操作時,可以使用 OkHttp,Retrofit的底層也是由 OkHttp 網絡加載庫來支持的。
關于 Retrofit 的原理,有三個十分重要的概念:『注解』,『動態代理』,『反射』。將會在以后逐步進行分析。
初步使用 Retrofit
Retrofit 在使用上與其他網絡開源庫有些區別,初次使用可能會感到困惑,其使用主要有四個步驟。
在使用前,我們首先假設我們要從某個 API 接口來獲取數據,這里我們使用一位博主所提供的接口。接口的 URL 地址如下:
添加依賴和權限
在 build.gradle 文件中添加依賴,在 Manifest.xml文件中添加所需的網絡權限。
// build.gradle
compile 'com.squareup.retrofit:retrofit:2.0.1-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
// AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
在 Retrofit 2.0 中,如果要將 JSON 數據轉化為 Java 實體類對象,需要自己顯式指定一個 Gson Converter。
定義接口
在這一步,需要將我們的 API 接口地址轉化成一個 Java 接口。
我們的 API 接口地址為:
轉化寫成 Java 接口為:
public interface APIInterface {
@GET("/users/{user}")
Call<TestModel> repo(@Path("user") String user);
在后文構造 Retrofit 對象時會添加一個 baseUrl(https://api.github.com)。
在此處 GET 的意思是 發送一個 GET請求,請求的地址為:baseUrl + "/users/{user}"。
{user} 類似于占位符的作用,具體類型由 repo(@Path("user") String user) 指定,這里表示 {user} 將是一段字符串。
Call<TestModel> 是一個請求對象,<TestModel>表示返回結果是一個 TestModel 類型的實例。
定義 Model
請求會將 Json 數據轉化為 Java 實體類,所以我們需要自定義一個 Model:
public class TestModel {
private String login;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
}
進行連接通信
現在我們有了『要連接的 Http 接口』和 『要返回的數據結構』,就可以開始執行請求啦。
首先,構造一個 Retrofit 對象:
Retrofit retrofit= new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
注意這里添加的 baseUrl 和 GsonConverter,前者表示要訪問的網站,后者是添加了一個轉換器。
接著,創建我們的 API 接口對象,這里 APIInterface 是我們創建的接口:
APIInterface service = retrofit.create(APIInterface.class);
使用 APIInterface 創建一個『請求對象』:
Call<TestModel> model = service.repo("Guolei1130");
注意這里的 .repo("Guolei1130") 取代了前面的 {user}。到這里,我們要訪問的地址就成了:
可以看出這樣的方式有利于我們使用不同參數訪問同一個 Web API 接口,比如你可以隨便改成 .repo("ligoudan")
最后,就可以發送請求了!
model.enqueue(new Callback<TestModel>() {
@Override
public void onResponse(Call<TestModel> call, Response<TestModel> response) {
// Log.e("Test", response.body().getLogin());
System.out.print(response.body().getLogin());
}
@Override
public void onFailure(Call<TestModel> call, Throwable t) {
System.out.print(t.getMessage());
}
});
至此,我們就利用 Retrofit 完成了一次網絡請求。
Retrofit 的注解
Retrofit 中有許多用到注解的地方,本次文章先了解他們的用法和作用,之后再深入了解其源碼特點。
Retrofit 中,有許多的注解:
其中,包含了與請求方法相關的 @GET、@POST、@HEAD、@PUT、@DELETA、@PATCH,和參數相關的@Path、@Field、@Multipart等。
在之前轉化接口時,我們是這樣寫的:
public interface APIInterface {
@GET("/users/{user}")
Call<TestModel> repo(@Path("user") String user);
可以看到 @GET 很明顯就是請求相關的;而 @Path 我們用它來充當一個占位符的功能,它是參數相關的。
Header 設置
當我們要設置網絡請求的 Header 參數時,Retrofit 提供兩種方式進行配置。
第一種是靜態配置,直接在接口中指定 Header 參數:
@Headers({
"User-Agent: Retrofit-Sample-App"
})
第二種是動態配置:
@GET("/user")
Call<TestModel> getUser(@Header("Authorization") String authorization)
在接口中注解但不指定,后面實例化請求體時可通過 .getUser 指定 Header。
GET 請求參數設置
在我們發送 GET 請求時,如果需要設置 GET 時的參數,Retrofit 注解提供兩種方式來進行配置。分別是 @Query(一個鍵值對)和 @QueryMap(多對鍵值對)。
Call<TestModel> one(@Query("username") String username);
Call<TestModel> many(@QueryMap Map<String, String> params);
POST 請求參數設置
POST 的請求與 GET 請求不同,POST 請求的參數是放在請求體內的。
所以當我們要為 POST 請求配置一個參數時,需要用到 @Body 注解:
Call<TestModel> post(@Body User user);
這里的 User 類型是需要我們去自定義的:
public class User {
public String username;
public String password;
public User(String username,String password){
this.username = username;
this.password = password;
}
最后在獲取請求對象時:
User user = new User("lgd","123456");
Call<TestModel> model = service.post(user);
就能完成 POST 請求參數的發送,注意該請求參數 user 也會轉化成 Json 格式的對象發送到服務器。
總結
以上便是對 Retrofit 的初步介紹和使用,可以看到如果 Web 服務器的 API 接口做的足夠規范,各個實體類的配置正確,使用 Retrofit 相比其他網絡加載庫,可以說是十分簡潔明了。
另外在搜索資料時,發現對于 Retrofit 的講解相對不多,Retrofit 2.0 與其之前的版本也有諸多不同,感謝各位博主提供的細致解讀與分享。
參考資料
Unable to create converter for my class in Android Retrofit library