Android Retrofit詳解

前言

Retrofit 是一個 RESTful 的 HTTP 網絡請求框架的封裝,網絡請求的工作本質上是 OkHttp 完成,而 Retrofit 僅負責 網絡請求接口的封裝

使用步驟

1.添加Retrofit庫的依賴:

implementation 'com.squareup.retrofit2:retrofit:2.0.2'
 implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
 implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'

后面三個是可選的,分別是數據解析器和gson,以及rxjava支持的依賴

2.創建 用于描述網絡請求 的接口
Retrofit將 Http請求 抽象成 Java接口:采用 注解 描述網絡請求參數 和配置網絡請求參數

public interface GetRequest_Interface {

    @GET("openapi.do?keyfrom=abc&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<Reception> getCall(@Field("name") String name);
    // @GET注解的作用:采用Get方法發送網絡請求
 
    // getCall() = 接收網絡請求數據的方法
    // 其中返回類型為Call<*>,*是接收數據的類(即上面定義的Translation類)
    // 如果想直接獲得Responsebody中的內容,可以定義網絡請求返回值為Call<ResponseBody>
}

3.創建Retrofit實例

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://fanyi.youdao.com/") //設置網絡請求的Url地址
                .addConverterFactory(GsonConverterFactory.create()) //設置數據解析器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

4.發送請求
請求分為同步請求和異步請求

        // 創建 網絡請求接口 的實例
        GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
        //對 發送請求 進行封裝
        Call<Reception> call = request.getCall("");
        call.enqueue(new Callback<Reception>() {
            //請求成功時回調
            @Override
            public void onResponse(Call<Reception> call, Response<Reception> response) {
                //請求處理,輸出結果
                response.body().show();
            }
            //請求失敗時候的回調
            @Override
            public void onFailure(Call<Reception> call, Throwable throwable) {
                System.out.println("連接失敗");
            }
        });

          //同步請求
        try {
            Response<Reception> response = call.execute();
            response.body().show();
        } catch (IOException e) {
            e.printStackTrace();
        }

response.body()就是Reception對象,網絡請求的完整 Url =在創建Retrofit實例時通過.baseUrl()設置 +網絡請求接口的注解設置(下面稱 “path“ )
整合的規則如下:


URL整合規則.png

注解

上面我們用了@GET注解來發送Get請求,Retrofit還提供了很多其他的注解類型


注解類型.png

第一類:網絡請求方法

網絡請求方法注解.png

1.@GET、@POST、@PUT、@DELETE、@HEAD分別對應 HTTP中的網絡請求方式
2.@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 不會做處理,所以要自行保證準確
}

第二類:標記

標記類注解.png

1.@FormUrlEncoded
表示發送form-encoded的數據,每個鍵值對需要用@Filed來注解鍵名,隨后的對象需要提供值。
2.@Multipart
表示發送form-encoded的數據(適用于 有文件 上傳的場景),每個鍵值對需要用@Part來注解鍵名,隨后的對象需要提供值。

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);

}

第三類:網絡請求參數

網絡請求參數注解.png

1.@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作用于方法

2.@Body
以 Post方式 傳遞 自定義數據類型 給服務器,如果提交的是一個Map,那么作用相當于 @Field,不過Map要經過 FormBody.Builder 類處理成為符合 Okhttp 格式的表單,如:

FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");

3.@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);

}

4.@Part & @PartMap
發送 Post請求 時提交請求的表單字段,與@Field的區別:功能相同,但攜帶的參數類型更加豐富,包括數據流,所以適用于 有文件上傳 的場景,與 @Multipart 注解配合使用

public interface GetRequest_Interface {

          /**
         * {@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);

        /**
         * PartMap 注解支持一個Map作為參數,支持 {@link RequestBody } 類型,
         * 如果有其它的類型,會被{@link retrofit2.Converter}轉換,如后面會介紹的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
         * 所以{@link MultipartBody.Part} 就不適用了,所以文件只能用<b> @Part MultipartBody.Part </b>
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);

        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
}

5.@Query和@QueryMap
用于 @GET 方法的查詢參數(Query = Url 中 ‘?’ 后面的 key-value)
如:url = http://www.println.net/?cate=android,其中,Query = cate
配置時只需要在接口方法中增加一個參數即可:

   @GET("/")    
   Call<String> cate(@Query("cate") String cate);
}

// 其使用方式同 @Field與@FieldMap,這里不作過多描述

6.@Path
URL地址的缺省值

public interface GetRequest_Interface {

        @GET("users/{user}/repos")
        Call<ResponseBody>  getBlog(@Path("user") String user );
        // 訪問的API是:https://api.github.com/users/{user}/repos
        // 在發起請求時, {user} 會被替換為方法的第一個參數 user(被@Path注解作用)
    }

7.@Url
直接傳入一個請求的 URL變量 用于URL設置

public interface GetRequest_Interface {

        @GET
        Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
       // 當有URL注解時,@GET傳入的URL就可以省略
       // 當GET、POST...HTTP等方法中沒有設置Url時,則必須使用 {@link Url}提供

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。