Retrofit2 初探:入門及其使用 完全解析
前言
相信大家對Retrofit一定不陌生,或多或少都聽過它的名字,它是一個最近很流行也很好用的網路請求庫,它對okHttp進行了封裝,加上利用了Java註解等特性,使得它能適應於靈活多變的網路請求情景。那麼接下來我們一起學習怎樣使用Retrofit2。
官網及相關檔案
在正式使用Retrofit2之前,我們要先準備好相應的檔案:
Retrofit2 GitHub地址
Retrofit2 官網地址
可以直接到官網下載相應的Jar包,或者直接通過Android Studiu的gradle新增如下依賴:
compile 'com.squareup.retrofit2:retrofit:2.1.0'
但是,只有Retrofit2是不夠的,我們還需要一些別的東西。從官網可以看出,Retrofit2預設是把響應反序列化到OkHttp的“ResponseBody”這個型別中,如果要讓它支援不同的響應型別(比如Json、xml等),就必須為Retrofit2新增轉換器,比如GsonConverterFactory。因此,我們還需要新增特定的依賴,官網給出瞭如下六種Converter:
- Gson: com.squareup.retrofit2:converter-gson
- Jackson: com.squareup.retrofit2:converter-jackson
- Moshi: com.squareup.retrofit2:converter-moshi
- Protobuf: com.squareup.retrofit2:converter-protobuf
- Wire: com.squareup.retrofit2:converter-wire
- Simple XML: com.squareup.retrofit2:converter-simplexml
- Scalars: com.squareup.retrofit2:converter-scalars
對於本文來說,將使用Gson來解析返回的Json資料,則新增如下依賴:
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
A Sample
Step 1.建立JavaBean類
建立JavaBean的目的很簡單,就是為了使Gson解析完成後的資料成功填充到相應的模型中,這也是必須的步驟,第一次使用Retrofit往往會忘記這一點,會造成經常報錯。我們要根據不同的返回資料的型別而編寫不同的JavaBean類。我們先看看提供的介面返回的資料是怎樣的:
從上圖看出,返回的是Json資料,用Gson來解析是恰當的,根據Json資料內的層次關係,我們可以如下編寫Bean類,新建WeatherBean.java
public class WeatherBean {
public List<Result> results;
public class Result{
public Location location;
public Now now;
public String last_update;
}
public class Location{
public String id;
public String name;
public String country;
public String path;
public String timezone;
public String timezone_offset;
}
public class Now{
public String text;
public int code;
public float temperature;
}
}
注意:編寫的Bean類裡面的成員變數的名字要與返回資料的欄位名相同,才能成功填充。
Step 2.建立interface 服務介面
新建IWeather.java:
public interface IWeather {
@GET("/v3/weather/now.json")
Call<WeatherBean> weather(@Query("key")String key,@Query("location")String location);
}
Retrofit2要求我們建立如上面所示的interface介面,而建立該介面的目的是,retrofit通過獲取介面的@GET註解裡面的值,與下面即將講到的baseUrl拼接成一個請求網址,另外通過呼叫介面的方法,填充相應引數之類的,這個下面會詳細講述,不要著急。
Step 3.建立Retrofit
在MainActivity.java中:
Retrofit retrofit2 = new Retrofit.Builder()
.baseUrl("https://api.thinkpage.cn")
.addConverterFactory(GsonConverterFactory.create())
.client(new OkHttpClient())
.build();
IWeather iWeather = retrofit2.create(IWeather.class);
通過Retrofit.Builder()方法來建立一個Retrofit例項,baseUrl()是設定Url,這是必須的,addConverterFactory()該方法是設定解析器,即上面提到的GsonConverterFactory,最後通過build()完成建立。接著通過Retrofit#creat方法來建立我們的服務,把IWeather介面實現了。
通過上述步驟,便建立了一個Retrofit例項,它包含了baseUrl等基本資訊,接著我們便要通過Retrofit例項與上面建立的服務介面聯絡起來,因為更詳細的訪問地址、請求引數等均存在於IWeather中,我們接著往下看。
Step 4.建立請求,設定請求引數,執行請求
在MainActivity.java中:
Call<WeatherBean> call = iWeather.weather("rot2enzrehaztkdk","beijing");
call.enqueue(new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
WeatherBean weatherBean = response.body();
Log.d("cylog",weatherBean.results.get(0).now.temperature+"");
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
Log.d("cylog", "Error" + t.toString());
}
});
通過呼叫IWeather的weather方法(我們在介面中定義的),把兩個關鍵引數傳遞了進入,這兩個引數均是使用@Query註解標記的,因此構成了url中的請求引數,而返回的call則是我們的請求。最後,呼叫call.enqueue方法,執行一個非同步請求,如果成功了,則回撥onResponse方法,否則回撥onFailure方法。另外,這裡補充一下:call.enqueue是一個非同步方法,不在同一執行緒內,而call.execute是一個同步方法,在同一執行緒內,希望注意一下。最後我們看看結果:
(注意:不要忘了網路許可權的新增~)
至此,一個基本的Retrofit網路請求從構建到執行已經解析完畢。
各種請求引數的寫法
1、固定的請求路徑
固定的請求路徑是指,請求地址是不變的,可以直接在程式碼中寫死的,如下所示:
public interface IWeather {
@GET("/v3/weather/now.json?key=rot2enzrehaztkdk&location=beijing")
Call<WeatherBean> weather();
}
把請求路徑以及引數全部寫在@GET註解內,一旦編譯後便不能修改了,適用於請求地址固定的情況下。
2、使用@Query 動態設定請求引數
這個與Sample設定的一樣:
public interface IWeather {
@GET("/v3/weather/now.json")
Call<WeatherBean> weather(@Query("key")String key,@Query("location")String location);
}
@GET只寫了前半部分的請求路徑,而後需要新增不同的引數來返回不同的資料,因此使用@Query,在方法的內部,為形參新增@Query註解,註解內部寫的是key值,我們呼叫該方法傳遞的引數是value值,形成”key=value”的引數,經過Retrofit內部處理,將該引數與@GET的路徑以及baseUrl的路徑組合在一起,形成一個完整的請求路徑。
3、使用@QueryMap 動態設定請求引數
與@Query類似,不過其形參變為了Map型別,Map中的key-value直接構成url請求引數中的key-value,程式碼如下所示:
public interface IWeather {
@GET("/v3/weather/now.json")
Call<WeatherBean> weather(@QueryMap Map<String,String> key,@QueryMap Map<String,String> location);
}
相應地,請求應該這樣寫:
Map<String,String> key = new HashMap<>();
key.put("key","rot2enzrehaztkdk");
Map<String,String> location = new HashMap<>();
location.put("location","beijing");
Call<WeatherBean> call2 = iWeather.weather(key,location);
4、請求路徑替換
@GET內的路徑可以不用寫死,利用形如“{xxx}”的形式佔位,然後在方法內利用@Path所註解的形參進行替換即可,具體見如下所示:
public interface IWeather {
@GET("/v3/{words}/now.json")
Call<WeatherBean> weather(@Path("words")String words,@Query("key")String key,@Query("location")String location);
}
只要在呼叫weather方法時,在第一個形參傳遞字串”weather”就可以把@GET註解的路徑替換成:”/v3/weather/now.json”,同時也不影響@Query的作用,因此適用於靈活多變的場景。
5、Post請求
上面所述的是@GET註解下的get請求,那麼post請求又應該怎樣寫呢?如下所示:
@POST("users/new")
Call<User> createUser(@Body User user);
通過@Post註解指定路徑,帶有@Body標誌的引數是post請求所傳送的請求體。
6、表單形式傳遞鍵值對
這個也是post請求方式的:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
除了@Post註解外,還多了@FormUrlEncoded註解,表示以表單鍵值對形式傳遞,方法內部的引數以@Field標記,註解內的是key值,而傳遞的形參是value值。
7、表單形式傳遞Map鍵值對
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@FieldMap Map<String,String> users);
通過@FieldMap註解標記的引數,傳遞一個Map集合,集合裡面有多少個鍵值對,則形成的url就包含多少個鍵值對。
8、上傳檔案
上傳檔案需要用到的註解是@Multipart,以及@Part,具體如下所示:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
@Multipart表示能使用多個Part,而@Part註解則是對引數進行標記,RequestBody是一種型別,是okHttp3裡面的一個類,既然請求引數是RequestBody型別的,那麼我們要把請求體封裝到RequestBody裡面去,通過RequestBody.creat()方法進行建立,該方法的引數支援如下型別:
第一個引數是MediaType,是媒體型別,第二個引數可為String、byte、file等,通過上述方法建立的RequestBody是一個請求體,將與其他的請求體一起傳送到服務端,它們的key值是@Part(“key”)註解的值,當然了,要與服務端的key值相對應才能請求成功。
本篇文章到此便結束了,關於Retrofit2的入門也講述完畢了,如果文章有錯誤的希望指出,以後學到新的知識也會繼續補充,謝謝你們的閱讀~