[Android] 一起來學好 Retrofit + MVVM (1)

Andy Lu
6 min readJun 4, 2021

前陣子看了 Netflix 上的影集 — Formula 1: 飆速求生,看完的心得是:下一季趕快出XD。

熱鬧的 F1 賽季已在三月份開始如火如荼般的進行,趁著這個熱潮,我們來做一個車手資料的 App 吧!

Google 「F1 Api 」後,找到 Ergast Developer API 這個網站有提供API。那麼我們二話不說,立刻開工吧。

本文會分成兩個部分

1. Retrofit — Http Client

2. MVVM — 資料綁定、資料顯示

流程如下:

利用 Retrofit 建立 Http Client,從 Webservice 中取得資料。取得資料後,便可以將資料透過 ViewModel ,同步更新在畫面上。

本篇文章將先介紹 Retrofit 的部分。

Why Retrofit?

  • 型別安全的 Http client
  • 使用 RESTful 的 API 設計
  • 簡單就能下載 JSON ,並轉換成 data class
  • 支援 coroutine (Retrofit 2.6)
  • 輕鬆完成關注點分離

How to use Retrofit?

Retrofit 分為三個部分

  1. Service:定義 HTTP API 的介面
  2. Model:儲存資料的 POJO
  3. Instance:Retrofit 的實體

實作流程

Step1: 在 build.gradle(app) 中,加入 retrofit 的 dependencies

build.gradle(app)
  • 其中 com.squareup.retrofit2:retrofit 是 Retrofit 的本體,com.squareup.retrofit2:converter-gson 是 Json Converter (gson)

Step 2: 定義 Model

根據這個 API http://ergast.com/api/f1/2021/drivers.json

我們可以獲得底下 JSON 格式的資料:

將 JSON 格式的資料轉換成 data class

使用 JSON To Kotlin 這套 plugin 轉換

DriverAPI.kt

*特別注意*

  1. 屬性名稱必須要與 JSON 的相同,否則轉換的時候就沒有辦法找到正確的屬性填入。
  2. 依照 Kotlin 的命名規則,所有屬性都應該是小寫的名稱開頭,如果因此跟原本欄位裡面的資料格式不同,可以使用 @SerializedName(“Drivers”) 設定為原本的名稱。

Step 3: 定義 HTTP API

http://ergast.com/api/f1/2021/drivers.json 為例,我們需要使用 http get 來取得這個 API 的資料,在 Retrofit 中,需要定義一個 interface ,用來定義這個 Server 所提供的 API。

F1ApiService.kt
  • Retrofit 是利用 annotation 來定義 API 的連線方式,以及其端點 end point。
  • 如上例,我們想將 2021 當作參數帶入,在函式的參數前面加上 @Path(“year”),就可以自動地將參數組合成 url 裡的數值。
  • 如果想要在 Get 的後方串上 Query 的條件呢?在參數前面加上 @Query 就可以將參數串在後方。→ http://ergast.com/api/f1/2021/drivers.json?limit=1,如下:
f1_driver_api_service2.kt
  • 最後,我們發現每一個 API 回傳的是 Response<API>,Response 可以讓我們更方便的處理資料。並且可以使用 suspend 關鍵字 ,Coroutine 來了!!!(Retrofit 2.6 開始支援)

Step4 : 建立 Retrofit 實體

  • Retrofit 是使用 Builder 來產生實體的,如下:
DriverViewModel.kt
  • baseUrl : 定義 Base Url ,在定義 API 時,就不需要每次都打同樣的內容,所以 baseUrl 的內容要填好。
  • addConverterFactory() :我們可以依照自己的喜好加上 Json converter,這邊採用的是 Gson。
  • create():帶入前面定義好的 API service。

Step5:取得資料

在上一步中,我們根據我們所提供的 API Service 建立了 Retrofit 的實體。是時候取得資料了。

  • 因為 getDriverByYear() 是一個 suspend function。所以這邊需要使用 viewModelScope 來限制此 Api 只能在這個 ViewModel 的 Life Cycle 中存活,當這個 ViewModel 被清除了,這邊的 api 呼叫也會被中斷。

小結

到這邊,Retrofit 的部分就完成了,我們複習一下,我們做了哪些事

  1. 在 build.gradle(app) 中的 dependencies 加入 Retrofit。
  2. 依照 API 的結果,建立 Model 。可以使用 Json To Kotlin 快速加入。
  3. 定義 API,在 Retrofit 2.6 後,開始支援 coroutine,所以每一個 API function 都可以使用 suspend 來定義是一個掛起函式。
  4. 在 Retrofit 中 定義 API 時,是使用 annotation 的方式進行宣告的,所以我們可以直接使用 @GET 來定義該函式是一個 HTTP Get API。
  5. 利用 Retrofit.Builder() 來建立 Retrofit 的實體。
  6. 建立 Retrofit 的實體後,將定義好的 APIService 帶入來產生一個 ProxyInstance。
  7. 這個 ProxyInstance 可以直接呼叫定義好的 API 函式,並且直接在後方用 let 串接,彷彿就像是同步的函式一樣。

如果本篇文章如果有幫助到你

請拍手👏鼓勵我~

你的鼓勵是我的動力

小祕技:拍手按鈕按著可以連續拍XD

參考

Retrofit 官網:https://square.github.io/retrofit/

--

--

Andy Lu
Andy Lu

Written by Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.

No responses yet