Retrofit 使用教學

markdown ## Retrofit簡介 Retrofit 是一個網路連結套件,可以在連結網路的時候做好封裝的效果,可以跟 OkHttp 以及 RxJava 合併使用 ## Retrofit應用 使用到的三方套件: ``` Java implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.squareup.okhttp3:okhttp:3.11.0' ``` 首先要先產生出Retrofit的實體物件: ```Kotlin class RetrofitServiceGenerator private constructor() { private val retrofit: Retrofit private val okHttpClient = OkHttpClient() init { retrofit = Retrofit.Builder() .baseUrl(Config.URL) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build() } companion object { private val manager = AppClientManager() val client: Retrofit get() = manager.retrofit } } ``` 上述可看到兩行程式碼: ```Kotlin .addConverterFactory(GsonConverterFactory.create()) ``` 這邊是使用Google出的Json處理工具來進行轉換(Gson) ```Kotlin .client(okHttpClient) ``` 另外可以看到.client這邊目前是使用預設的okHttpClient,Retrofit本身底層是使用OkHttp的Client,若有一些特殊情境(ex. 網路回傳錯誤代碼)可以寫自己的攔截器或是調整設定 實體物件建立完後,再來示範串接一個RESTFUL API 隨便拿一個網路上提供的GET網址如下 ```Kotlin https://jsonplaceholder.typicode.com/posts ``` 回傳資料格式如下: ```Kotlin [ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }, //... ] ``` 範例回傳的格式是由四個欄位組成,因此我們可以將Response 宣告成以下類別: ```Kotlin class GetSampleElementResponse { @SerializedName("userId") var userId: Int = 0 @SerializedName("id") var id: Int = 0 @SerializedName("title") var title: String? = null @SerializedName("body") var body: String? = null } ``` 此時也宣告一個interface透過retrofit使用這個response class,API回來的資訊為非同部,因此使用Call的方式來處理,retrofit 會對這個行為進行非同步處理,如下: ```Kotlin interface ApiService { @GET("/posts") fun getSampleElement(): Call> } ``` 設定完成後就可以開始使用Retrofit,宣告一個按鈕並寫其觸發事件: ```Kotlin test.setOnClickListener { val apiService = RetrofitServiceGenerator.client.create(ApiService::class.java) apiService.index().enqueue(object : Callback> { override fun onResponse(call: Call>, response: Response>) { val sb = StringBuffer() val list = response.body() for (p in list!!) { sb.append(p.body) sb.append("\n") sb.append("---------------------\n") } tv.text = sb.toString() } override fun onFailure(call: Call>, t: Throwable) { } }) } ``` 當我們把資料抓取回來就可以透過Response物件取出我們的Json,Retrofit會自動幫我們把對應的Json轉成對應的物件GetSampleElementResponse,根據一開始interface定義好的方式轉成List,這樣就可以直接使用List。 ## Retrofit 延伸功能 ### APIService 其他使用方式 在範例中我們是使用一個簡單的Get方法,在APIService中還有許多使用方式 網址後面可以直接帶入相對應的變數: ```Kotlin @GET("api/user/detail/{listid}") fun getSampleElement(@Path("listid")id: String): Call> ``` 若你的參數是裝在Body裡面,可以這樣使用 ```Kotlin @GET("api/user/detail/{listid}") fun getSampleElement(@Path("listid")id: String , @Body requestBody: GetSampleRequestBody): Call> ``` 若帶入的參數很多時,可以使用QueryMap包起來 ```Kotlin @GET("api/user/detail/{listid}") fun getSampleElement(@Path("listid")id: String , @QueryMap map: Map): Call> ``` ### OkHttp提供攔截器功能 特殊情境Sample:Server端若回傳307(或是其它需特殊處理的Error Code)錯誤後我們要自己手動轉location所導的網址,可能就需要自己寫一個攔截器,去做重新轉址的動作 ```Java OkHttpClient client = new OkHttpClient.Builder() .followRedirects(false); //禁止OkHttp的重新轉址動作 .addInterceptor(new RedirectInterceptor()) //我們自己的攔截器 .build(); ``` ```Java public class RedirectInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { okhttp3.Request request = chain.request(); Response response = chain.proceed(request); int code = response.code(); if (code == 307) { //拿要轉的網址 String location = response.headers().get("Location"); LogUtils.e("重新導的網址:", "location = " + location); Request newRequest = request.newBuilder().url(location).build(); response = chain.proceed(newRequest); } return response; } } ```

留言

這個網誌中的熱門文章

Privacy Policy