1. 程式人生 > >Retrofit 2.0 使用教程

Retrofit 2.0 使用教程

本文轉載自:http://blog.csdn.net/carson_ho/article/details/73732076

前言

  • Andrroid開發中,網路請求十分常用
  • 而在Android網路請求庫中,Retrofit是當下最熱的一個網路請求庫

Github截圖

  • 今天,我將獻上一份非常詳細Retrofit v2.0的使用教程,希望你們會喜歡。

目錄

目錄

1. 簡介

Retrofit簡介

特別注意:

  • 準確來說,Retrofit 是一個 RESTful 的 HTTP 網路請求框架的封裝。
  • 原因:網路請求的工作本質上是 OkHttp 完成,而 Retrofit 僅負責 網路請求介面的封裝

本質過程

  • App應用程式通過 Retrofit 請求網路,實際上是使用 Retrofit 介面層封裝請求引數、Header、Url 等資訊,之後由 OkHttp 完成後續的請求操作
  • 在服務端返回資料之後,OkHttp 將原始的結果交給 Retrofit,Retrofit根據使用者的需求對結果進行解析

2. 與其他開源請求庫對比

除了Retrofit,如今Android中主流的網路請求框架有:

  • Android-Async-Http
  • Volley
  • OkHttp

下面是簡單介紹:

網路請求載入 - 介紹

一圖讓你瞭解全部的網路請求庫和他們之間的區別!

網路請求庫 - 對比

附:各個主流網路請求庫的Github地址

3. 使用介紹

使用 Retrofit 的步驟共有7個:

步驟1:新增Retrofit庫的依賴 
步驟2:建立 接收伺服器返回資料 的類 
步驟3:建立 用於描述網路請求 的介面 
步驟4:建立 Retrofit 例項 
步驟5:建立 網路請求介面例項 並 配置網路請求引數 
步驟6:傳送網路請求(非同步 / 同步)

封裝了 資料轉換、執行緒切換的操作

步驟7: 處理伺服器返回的資料

接下來,我們一步步進行講解。

步驟1:新增Retrofit庫的依賴

1. 在 Gradle加入Retrofit庫的依賴

由於Retrofit

是基於OkHttp,所以還需要新增OkHttp庫依賴

build.gradle

dependencies {
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    // Retrofit庫
    compile 'com.squareup.okhttp3:okhttp:3.1.2'
    // Okhttp庫
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2. 新增 網路許可權 
AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
  • 1
  • 1

步驟2:建立 接收伺服器返回資料 的類

Reception.Java

public class Reception {
    ...
    // 根據返回資料的格式和資料解析方式(Json、XML等)定義
    // 下面會在例項進行說明
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

步驟3:建立 用於描述網路請求 的介面

  • Retrofit將 Http請求 抽象成 Java介面:採用 註解 描述網路請求引數 和配置網路請求引數 
    1. 用 動態代理 動態 將該介面的註解“翻譯”成一個 Http 請求,最後再執行 Http 請求 
    2. 注:介面中的每個方法的引數都需要使用註解標註,否則會報錯

GetRequest_Interface.interface
public interface GetRequest_Interface {

    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<Translation>  getCall();
    // @GET註解的作用:採用Get方法傳送網路請求

    // getCall() = 接收網路請求資料的方法
    // 其中返回型別為Call<*>,*是接收資料的類(即上面定義的Translation類)
    // 如果想直接獲得Responsebody中的內容,可以定義網路請求返回值為Call<ResponseBody>
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
下面詳細介紹Retrofit 網路請求介面 的註解型別。

註解型別

註解型別

註解說明

第一類:網路請求方法

網路請求方法註解

詳細說明: 
a. @GET、@POST、@PUT、@DELETE、@HEAD 
以上方法分別對應 HTTP中的網路請求方式

public interface GetRequest_Interface {

    @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<Translation>  getCall();
    // @GET註解的作用:採用Get方法傳送網路請求
    // getCall() = 接收網路請求資料的方法
    // 其中返回型別為Call<*>,*是接收資料的類(即上面定義的Translation類)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
此處特意說明URL的組成:Retrofit把 網路請求的URL 分成了兩部分設定:
// 第1部分:在網路請求介面的註解設定
 @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation>  getCall();

// 第2部分:在建立Retrofit例項時通過.baseUrl()設定
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://fanyi.youdao.com/") //設定網路請求的Url地址
                .addConverterFactory(GsonConverterFactory.create()) //設定資料解析器
                .build();

// 從上面看出:一個請求的URL可以通過 替換塊 和 請求方法的引數 來進行動態的URL更新。
// 替換塊是由 被{}包裹起來的字串構成
// 即:Retrofit支援動態改變網路請求根目錄
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 網路請求的完整 Url =在建立Retrofit例項時通過.baseUrl()設定 +網路請求介面的註解設定(下面稱 “path“ )
  • 具體整合的規則如下:

URL整合規則

建議採用第三種方式來配置,並儘量使用同一種路徑形式。

b. @HTTP

  • 作用:替換@GET、@POST、@PUT、@DELETE、@HEAD註解的作用 及 更多功能拓展
  • 具體使用:通過屬性method、path、hasBody進行設定
public interface GetRequest_Interface {
    /**
     * method:網路請求的方法(區分大小寫)
     * path:網路請求地址路徑
     * hasBody:是否有請求體
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getCall(@Path("id") int id);
    // {id} 表示是一個變數
    // method 的值 retrofit 不會做處理,所以要自行保證準確
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第二類:標記

標記類註解

a. @FormUrlEncoded

  • 作用:表示傳送form-encoded的資料

每個鍵值對需要用@Filed來註解鍵名,隨後的物件需要提供值。

b. @Multipart


  • 作用:表示傳送form-encoded的資料(適用於 有檔案 上傳的場景) 

每個鍵值對需要用@Part來註解鍵名,隨後的物件需要提供值。 
具體使用如下: 
GetRequest_Interface

public interface GetRequest_Interface {
        /**
         *表明是一個表單格式的請求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示將後面的 <code>String name</code> 中name的取值作為 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

        /**
         * {@link Part} 後面支援三種類型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意型別
         * 除 {@link okhttp3.MultipartBody.Part} 以外,其它型別都必須帶上表單欄位({@link okhttp3.MultipartBody.Part} 中已經包含了表單欄位的資訊),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

}

// 具體使用
       GetRequest_Interface service = retrofit.create(GetRequest_Interface.class);
        // @FormUrlEncoded 
        Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);

        //  @Multipart
        RequestBody name = RequestBody.create(textType, "Carson");
        RequestBody age = RequestBody.create(textType, "24");

        MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
        Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

第三類:網路請求引數

網路請求引數註解

詳細說明

a. @Header & @Headers

  • 作用:新增請求頭 &新增不固定的請求頭
  • 具體使用如下:
// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()

// 以上的效果是一致的。
// 區別在於使用場景和使用方式
// 1. 使用場景:@Header用於新增不固定的請求頭,@Headers用於新增固定的請求頭
// 2. 使用方式:@Header作用於方法的引數;@Headers作用於方法
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

b. @Body


  • 作用:以 Post方式 傳遞 自定義資料型別 給伺服器
  • 特別注意:如果提交的是一個Map,那麼作用相當於 @Field 

不過Map要經過 FormBody.Builder 類處理成為符合 Okhttp 格式的表單,如:

FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

c. @Field & @FieldMap

  • 作用:傳送 Post請求 時提交請求的表單欄位
  • 具體使用:與 @FormUrlEncoded 註解配合使用
public interface GetRequest_Interface {
        /**
         *表明是一個表單格式的請求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示將後面的 <code>String name</code> 中name的取值作為 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

/**
         * Map的key作為表單的鍵
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);

}

// 具體使用
         // @Field
        Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);

        // @FieldMap
        // 實現的效果與上面相同,但要傳入Map
        Map<String, Object> map = new HashMap<>();
        map.put("username", "Carson");
        map.put("age", 24);
        Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28