Retrofit 2.x 系列之一 - Retrofit的使用姿勢(基礎篇)

文章使用的Retrofit版本爲:2.3.0

Retrofit已經問世很久了,現在再來討論Retrofit的使用不免有些晚,但是也是爲了鞏固自己的知識,話不多說,直接開始:

Retrofit是什麼?

其實Retrofit是對網絡請求的一種封裝,實際進行網絡請求的並不是它本身,Retrofit內部依賴了okhttp與okio,就像我們在使用okhttp時進行封裝一樣,Retrofit通過一系列初始化配置之後,讓我們可以通過註解的方式就能進行網絡請求,很大程度上簡化了我們在實際請求時所需要做的操作。
Retrofit內部依賴

Retrofit怎麼用?
  1. 添加依賴:
implementation 'com.squareup.retrofit2:retrofit:2.3.0'

因爲Retrofit已經內部依賴了okhttp,所以我們不需要額外再去添加依賴了。

  1. Retrofit初始化配置
object RetrofitCreate {
    fun getApi(): Api {
        return Retrofit.Builder()
                .baseUrl("http://www.baidu.com/")
                .client(OkHttpClient())
                .build()
                .create(Api::class.java)
    }
}

我們從以上的幾個方法開始看:
1、baseUrl()必需項,設置的是接口請求中的url基地址,必須以 / 結尾,否則會報錯(原因我們在往後源碼解析的文章中能知道),並且在調用A接口時如果註解中的地址已經包含了基地址,那麼A接口每次調用時都以它自己的基地址覆蓋設置的baseUrl,其他接口還是使用baseUrl。
2、client()可選項,設置的是OkhttpClient ,我們可以對OkHttpClient進行自定義,如果不配置的話Retrofit會使用默認的OkhttpClient。
3、cteate()必需項,指定我們將Retrofit的初始化與哪一個配置接口相結合。

  1. 添加請求配置的接口

這裏以 GET 請求舉例

interface Api {
    @GET("hello/world")
    fun getHelloWorld(@Query("name") name: String): Call<String>
}

@GET("hello/world") 這個方法上的註解就定義了這個接口的請求方式爲 GET、url爲 hello/world ,這裏的url會和第二步中Retrofit中的初始化配置協同工作,並且,如果你這裏寫的是完整路徑,那麼在Retrofit初始化時設置的baseUrl將在此次接口調用中無效,注意是 此次,並不會就此覆蓋baseUrl。

@Query 這個參數的註解含義爲參數名爲字符串 name ,參數的值爲調用時傳入的值,方法的註解和參數的註解是搭配來使用的,這個我們稍後介紹。

Call<String> 爲返回值,返回類型爲 String,call 爲Retrofit的包裝類,能夠調用同步、異步方法發起請求,實際發起請求的操作是轉交到了Okhttp和okio去做。

發起異步的 GET 請求:

RetrofitCreate.getApi().getHelloWorld("jerry").enqueue(object:Callback<String>{
        override fun onFailure(p0: Call<String>?, p1: Throwable?) {
        }

        override fun onResponse(p0: Call<String>?, p1: Response<String>?) {
        }
    })

結合圖示代碼的完整請求信息如下:
請求接口:http://www.baidu.com/hello/world?name=jerry
請求方法:GET
因爲是 get 請求,參數已經拼接到了 url 上。

至此,一個簡單的請求我們就完成了。當然,Retrofit 可不僅僅只有這點內容,Retrofit 的使用就是對其內部定義的各種註解的使用,所以我們就從註解開始。

Retrofit的註解

Retrofit的註解類型
這就是所謂的開局一張圖,剩下全靠吹:

  1. 方法註解
註解 作用
@GET 表明HTTP請求方法爲GET,(可選)註解的value屬性用來設置相對/絕對url
@POST 表明HTTP請求方法爲POST,(可選)註解的value屬性用來設置相對/絕對url
@PUT 表明HTTP請求方法爲PUT,(可選)註解的value屬性用來設置相對/絕對url
@DELETE 表明HTTP請求方法爲DELETE ,(可選)註解的value屬性用來設置相對/絕對url
@HEAD 表明HTTP請求方法爲HEAD,(可選)註解的value屬性用來設置相對/絕對url
@PATCH 表明HTTP請求方法爲PATCH,(可選)註解的value屬性用來設置相對/絕對url
@OPTIONS 表明HTTP請求方法爲OPTIONS,(可選)註解的value屬性用來設置相對/絕對url
@HTTP 通過@HTTP註解指定http協議的請求方法,是否允許body,(可選)註解的value屬性用來設置相對/絕對url
@Headers 使用註解的value值數組作爲HTTP的請求頭,用於一些固定的Header參數

1.1. 標記類註解

註解 作用
@FormUrlEncoded 表明發起HTTP請求的RequestBody是form表單方式
@Multipart 表明發起HTTP請求的RequestBody是Multipar方式
@Streaming 用於直接返回流的函數
  1. 參數註解
註解 作用
@Url HTTP請求的url路徑(相對/絕對),可以包含{path},如:http://xxx.com/{path1}/detail
@Body 表明此參數用作HTTP請求的body
@Path 用於動態替換URL路徑中的 {path}
@Field 表明此參數用作HTTP請求的form表單參數,表單參數的key爲註解的value值
@FieldMap 以map形式傳入的form表單參數
@Part 表明參數爲Http的multipart參數之一
@PartMap 以map形式傳入的multipart參數表
@Query GET方法的query參數,用於拼接完整請求路徑
@QueryMap 以map傳入的GET方法的query參數,用於拼接完整請求路徑
@Header 表明此參數用作HTTP請求的header,請求頭的key爲註解的value值
@HeaderMap 以map形式傳入的多個header鍵值對

直接用代碼展示各個註解的使用方式:

interface Api {

    //使用@Headers添加多個請求頭
    @Headers("User-Agent:android", "apikey:123456789")
    @POST
    fun post(@Url url: String, @QueryMap map: Map<String, String>): Call<Any>

    @GET("hello/world")
    operator fun get(@Header("token") token: String, @Query("id") activeId: Int): Call<Any>

    @GET("hello/world")
    fun ActiveList(): Call<Any>

    @POST("hello/world")
    fun post2(@QueryMap map: Map<String, String>): Call<Any>

    /**
     * 很多情況下,我們需要上傳json格式的數據。比如當我們註冊新用戶的時候,因爲用戶註冊時的數據相對較多,
     * 並可能以後會變化,這時候,服務端可能要求我們上傳json格式的數據。此時就要@Body註解來實現。
     * 直接傳入實體,它會自行轉化成Json
     */
    @POST("hello/{url}/world")
    fun login(@Path("url") url: String, @Body post: Any): Call<Any>

    /**
     * 單張圖片上傳
     * retrofit 2.0的上傳和以前略有不同,需要藉助@Multipart註解、@Part和MultipartBody實現。
     */
    @Multipart
    @POST("{url}")
    fun upload(@Path("url") url: String, @Part file: MultipartBody.Part): Call<Any>

    /**
     * 多張圖片上傳
     */
    @Multipart
    @POST("hello/world")
    fun upload(@PartMap map: Map<String, MultipartBody.Part>): Call<Any>

    /**
     * 圖文混傳
     */
    @Multipart
    @POST()
    fun register(@Body post: Any, @PartMap map: Map<String, MultipartBody.Part>): Call<Any>

    /**
     * 文件下載
     */
    @Streaming
    @GET
    fun downloadPicture(@Url fileUrl: String): Call<Any>

    /**
     * 這裏需要注意的是如果下載的文件較大,比如在10m以上,那麼強烈建議你使用@Streaming進行註解,否則將會出現IO異常.
     */
    @Streaming
    @GET
    fun downloadPicture2(@Url fileUrl: String): Call<Any>

    @POST
    @FormUrlEncoded
    fun executePost(@FieldMap maps: Map<String, Any>): Call<Any>
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章