35

Android App 開發實戰系列 Part 2. 資料來源 API

 3 years ago
source link: https://enginebai.com/2020/08/05/moviehunt-part-2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Part1. 我們從專案的起源、需求、設計和架構以及套件講起,Part2. 我們就開始來實作,首先先從「資料來源 API」開始講解和實作。

y2QrmyQ.png!web

完整程式碼 https://github.com/enginebai/MovieHunt 已經釋出 ,可以下載程式碼邊看碼邊學習,歡迎給星 :star: 支持。這一系列文章是有連貫性的,如果還沒看過前面文章,建議先去看過前面的章節。

這章節對應到Part 1. 的 MVVM Architecture 架構圖就是底層 Model 的 Remote:

qIJBvir.png!web

資料來源

我們的 MovieHunt app 的電影資料是採用 The Movie Database (以下簡稱 TMDB ) 當作來源,在使用這個 API 之前我們要先去 https://www.themoviedb.org/settings/api 申請一組 Developr API Key。

申請好後複製 API Key,回到專案在 buildSrc/src/main/kotlin/ 目錄底下新增檔案 ApiKey.kt ,然後加上下面的一行程式碼,其中 90c0****655 就是 Developer API Key,要替換成你申請的 API Key。

const val TMDB_API_KEY = "\"90c0*******************655\""

你可能會好奇為何要加反斜線和雙引號,等等會講解到,先照著做直接複製貼上。

重要:這個檔案因為包含機密的 API Key,所以我們不會加到版本控管裡面,所以要從 .gitignore 裡面排除掉,自己要好好保管這 Key。

RESTful API library – Retrofit 

接下來我們要開始使用接 API,我們會使用一個在 Android 開發中知名的套件 Retrofit ,首先我們先針對 Retrofit 做一些基本的設定(import dependency 就不贅述了):

1. 設定 Base URL

我們會在我們的 Build Script Config.kt 裡面設置我們的 Base URL:

加完之後要執行 Gradle Sync + Make Project 一次讓設定可以加入到 BuildConfig

這邊要注意, API_ROOT / IMAGE_API_ROOT 跟之前加入的 TMDB_API_KEY 一樣,要加反斜線和雙引號,原因在於 buildConfigFiels() 方法有三個參數,分別是變數型態、名稱和值(字串型態),如果去看這個方法的原始碼:

public void buildConfigField(
            @NonNull String type, @NonNull String name, @NonNull String value)

可以看到最後一個 value 是字串型態,如果你今天要設定一個數字,是要寫成 "1234"如果要設定這個變數是 String,需要多一組雙引號 ,也就是我們另外加的反斜線和雙引號。

Retrofit 就可以增加 baseUrl(url: String)

Retrofit.Builder()
    .baseUrl(BuildConfig.API_ROOT)
    .build()

(你可以嘗試把 API_ROOT 改成 = “http://api…” 然後編譯看看,看會發生什麼事情,就更可以理解上面說要多加一組雙引號的原因了。)

你可能會問「這個網址為何要在 Build Script 設置呢?」為何不直接寫在程式裡面呢?這是因為考量到 設置的靈活性 ,有一種常見的情況是我們有不同的 API 環境,Base URL 要分 Staging / Production 兩個不同的網址,這時候我們就可以使用 Android 的 build variants 來區分(如下面範例),這時候把 URL 寫在 Build Script,這樣的做法是比較具有彈性的。

2. 設置 Retrofit

這邊 CallAdapter 的用途是將 Retrofit 每個方法的回傳值 Call 轉換成另外的型態,我們是用 RxJava 當作回傳型態,所以增加了 RxJava2CallAdapterFactory.create()

Converter 的用途是讓 Retrofit API 回傳的 HTTP 字串可以轉換成我們自己定義的資料型態 (反序列化 Deserialize)以及轉換回去(序列化 Serialize),我們是使用 Gson ,所以增加了 GsonConverterFactory.create() 。不知道什麼叫「序列化」的朋友們這邊幫你做個快速的解釋,更詳盡的解釋可以自己搜尋:

  • Serialization 序列化:data object (kotlin 程式端使用的物件) -> json string (底層傳遞)
  • Deserialization 反序列化:json string -> data object

API 介面

API Service Interface

接下來就要來定義我們的 API 介面,我們這邊只會用到兩支 API:列表 /movie/{list} 和詳細頁 /movie/{movieId}

Retrofit 可以讓每個 Endpoint 都變成一個介面的方法,透過 Annotation ( @GET, @Path, @Query …等等)來定義 API 的用法和參數,詳細使用方式可以參考 文件 ,我們不多做額外的說明。

這邊特別要講的是每個 API 方法的回傳值,在 RxJava (2 以上) 裡面 Observable 主要有三種型態: Observable / Single / Maybe ,而這兩個 API 只有兩種結果:成功回傳資料或者失敗,所以我們都選用 Single 當作回傳值。

Data Class for Response

TMDB API 回傳的格式是 JSON,而我們會利用 GSON 將 JSON 轉換成我們程式內的資料物件:

我們用 Data Class 當作 API 回傳的資料型態,API Response 可以參考上面兩個 API 的連結。這邊比較重要的是 在於除了 id 之外,其他所有欄位皆為 Nullable,這樣做在使用這些欄位時可以強制讓你考慮到沒有該欄位值的情況 ,因為可能 API 發生錯誤而沒有這個欄位值,或者哪天 API 拿掉這個欄位值,你的 App 都假設欄位是可空,且都有處理空值,那麼你就不用擔心發生 NullPointerExceptioin (NPE) 而閃退。

另外,Gson 預設是可以用 Property 的名稱來和 API 欄位對上,不過考量到 API 欄位的命名規範可能和 Kotlin 建議的命名規範不同(API 使用底線分隔,Kotlin 使用駝峰式命名),所以我們還是使用 Gson 提供的 @SerializedName("...") 來指定 API 欄位名稱。

Http Client setup + Interceptor

Retrofit 底層也是使用 OkHttp 去完成工作,所以我們也可以設定一下 Retrofit 使用我們自己的 OkHttp 實體,而且 官方文件 提到比較好的作法是讓整個 App 都使用單一實體(考量到效能、連線數、延遲…等因素)。

Interceptor

3Qfqqez.png!web

TMDB 要求每一個 API Request 都要帶 API Key 在 Query String ( /movie/popular?api_key=xxx" ),Retrofit 是有提供 @Query 讓我們可以當作方法的參數傳入:

但是這樣就會變成每一個 API 方法都要增加這個參數,之後 API 數量變多,這樣做法肯定不是一個很好的設計,那該怎麼辦呢?

OkHttp 的 Interceptor 可以來解決這樣的需求,它可以攔截所有送出的 Request / Response,我們就可以用它來幫我們的 Request / Response 做加工,像官方就有提供 HttpLoggingInterceptor 可以印出我們送出的所有 API 的詳細內容。那我們自己寫一個 Interceptor 來幫我們所有 API Request 都加上 API Key:

完成之後,我們就可以把 ApiInterceptor 加到 OkHttp client 裡面了, BuildConfig.TMDB_API_KEY 已經在上面講解設定 Base URL 的時候加入了,在這邊就會用上,再來就把 Interceptor 加入到 OkHttp 的初始化當中。

大功告成!我們資料來源章節就講到這,我們用到了 Retrofit + OkHttp + Gson 三個主要套件,更詳盡的用法可以參考各自的官方文件。 下一個章節會講解 Repo + Paging 的概念,會使用這篇的資料來源和 API,所以務必熟悉上面講解的內容。

如果你有任何和此專案相關的疑問,歡迎留言給我交流或討論。完整程式碼: https://github.com/enginebai/MovieHunt 歡迎 Fork + Star :star: 支持。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK