文章使用的Retrofit版本爲:2.3.0
Retrofit已經問世很久了,現在再來討論Retrofit的使用不免有些晚,但是也是爲了鞏固自己的知識,話不多說,直接開始:
Retrofit是什麼?
其實Retrofit是對網絡請求的一種封裝,實際進行網絡請求的並不是它本身,Retrofit內部依賴了okhttp與okio,就像我們在使用okhttp時進行封裝一樣,Retrofit通過一系列初始化配置之後,讓我們可以通過註解的方式就能進行網絡請求,很大程度上簡化了我們在實際請求時所需要做的操作。
Retrofit怎麼用?
- 添加依賴:
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
因爲Retrofit已經內部依賴了okhttp,所以我們不需要額外再去添加依賴了。
- 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的初始化與哪一個配置接口相結合。
- 添加請求配置的接口
這裏以 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的註解
這就是所謂的開局一張圖,剩下全靠吹:
- 方法註解
註解 | 作用 |
---|---|
@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 | 用於直接返回流的函數 |
- 參數註解
註解 | 作用 |
---|---|
@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>
}