1. 程式人生 > >Retrofit2 初探:入門及其使用 完全解析

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()方法進行建立,該方法的引數支援如下型別:
requestbody#creat
第一個引數是MediaType,是媒體型別,第二個引數可為String、byte、file等,通過上述方法建立的RequestBody是一個請求體,將與其他的請求體一起傳送到服務端,它們的key值是@Part(“key”)註解的值,當然了,要與服務端的key值相對應才能請求成功。

本篇文章到此便結束了,關於Retrofit2的入門也講述完畢了,如果文章有錯誤的希望指出,以後學到新的知識也會繼續補充,謝謝你們的閱讀~