當有些資料是想要從網絡上獲取到app顯示時
就須要串接資料所提供的api
可以利用retrofit這個工具進行
implementation "com.squareup.retrofit2:retrofit:2.3.0"
implementation "com.squareup.retrofit2:converter-scalars:2.3.0"
Retrofit根據來自Web服務的內容為應用程序創建網絡API,支援的Web內容包含XML與JSON格式
這裡我是用高雄市政府公開的臨時停車資訊做練習,可查詢其公開的網頁點選JSON,通常會是類似這樣的網址https://api.kcg.gov.tw/api/service/get/897e552a-2887-4f6f-a6ee-709f7fbe0ee3
內容可能是密密麻麻一大串文字
因爲我們要將接進來的資訊程式化,所以會做成data class
可以利用例如https://jsoneditoronline.org/ 之類的網站協助解析
不過,android studio也有插件可以協助
到setting選Plugins,收尋JsonToKotlinClass,然後安裝
新增一個ParkingInfo.kt,右鍵開啓選單選Generate,再選Kotlin classes from JSON開啓視窗,這裡可以將整個Json文字,或只需要該網址貼上,解析完後新增
就會協助我們產生data class
data class ParkingInfo(
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("id")
val id: String = "", // 914766c5-8eda-42df-ac8b-f207b6fb0dd5
@SerializedName("isImage")
val isImage: Boolean = false, // false
@SerializedName("success")
val success: Boolean = false // true
) {
data class Data(
@SerializedName("seq")
val seq: Int = 0, // 1
@SerializedName("可提供小型車停車位")
val 可提供小型車停車位: String = "", // 10
@SerializedName("地址")
val 地址: String = "", // 金龍路65號
@SerializedName("臨時停車處所")
val 臨時停車處所: String = "", // 老人文康活動中心
@SerializedName("行政區")
val 行政區: String = "" // 大社區
)
}
不過因爲對方提供的內容關係,有可能會看到例如val 可提供小型車停車位: String = ""
以中文爲變數名稱
這時就可利用@SerializedName
將對方中文名稱傳入,我們的變數另外命名,這樣就可對應
@SerializedName("可提供小型車停車位")
val carSpace: String
data class name也可修改爲自己要的,調整後如下
data class ParkingInfo(
@SerializedName("isImage")
val isImage: Boolean,
@SerializedName("data")
val `data`: List<ParkingDetail>,
@SerializedName("id")
val id: String,
@SerializedName("success")
val isSuccess: Boolean
) {
data class ParkingDetail(
@SerializedName("行政區")
val gov: String,
@SerializedName("臨時停車處所")
val parkingPlace: String,
@SerializedName("可提供小型車停車位")
val carSpace: String,
@SerializedName("地址")
val address: String,
@SerializedName("seq")
val seq: Int
)
}
完成後就來設定API
新增一個ApiService.kt檔案,並宣告BASE_URL爲const val,(kotlin)
要注意BASE_URL內的網址須爲斜槓/
結尾
private const val BASE_URL =
"https://api.kcg.gov.tw/api/service/get/"
define一個interface用於向web server做http請求
(須要import retrofit2.http.GET , retrofit2.call)
interface ParkingApiService {
@GET("897e552a-2887-4f6f-a6ee-709f7fbe0ee3")
fun getParkingLot(): Call<ParkingInfo>
}
本次任務是從Web獲取資料,所以interface內只需定義一個回傳資料的getParkingLot()方法
getParkingLot()並會建立一個Call object用於發起請求
而在此方法前的@GET
,是將欲請求的網址路徑或endpoint傳入
如果要用網址的話,就可設定爲https://api.kcg.gov.tw/api/service/get/897e552a-2887-4f6f-a6ee-709f7fbe0ee3
用於endpoint的話,retrofit就會將此endpoint接在BASE_URL後
以retrofit builder建立一個retrofit object
object ParkingApi{
private val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
val retrofitService: ParkingApiService = retrofit.create(ParkingApiService::class.java)
}
以retrofit建立web service api至少包含二個方法:baseUrl()
,addConverterFactory()
轉換器converter告訴retrofit如何處理從web取回的資料
GsonConverterFactory會幫我們將拿到的Json,轉換爲data class所設定的格式,最後呼叫build()建立
接着以create()
將interface ParkingApiService實作出來
因爲建立api是比較耗能的,而且app也只需要一個retrofit實例
所以將其宣告爲object單例
向Web發出請求需要app告訴android系統開啓使用網路的權限
在app/manifests/AndroidManifest.xml
新增<uses-permission android:name="android.permission.INTERNET" />
位置如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.carparking">
<uses-permission android:name="android.permission.INTERNET" />
<application ...
..
.
到MainActivity中,準備呼叫api
ParkingApi.retrofitService.getParkingLot()
.enqueue(object : retrofit2.Callback<ParkingInfo> {})
使用ParkingApi.retrofitService.getParkingLot()
回傳的Call object呼叫enqueue()
,將向網路發起request請求排入後台執行緒
object會顯示錯誤提示,因爲此處有二個fun必須複寫
分別是onResponse()
與onFailure()
,按ctrl+oonFailure()
就是當發出的request沒有獲得正確回應時,要做的事
我們先寫log,如果fail,就讓它丟個訊息
override fun onFailure(call: Call<ParkingInfo>, t: Throwable) {
Log.e("Failure", t.message)
}
onResponse()
是我們主要看的,因爲要成功接進來才能拿到資料
override fun onResponse(call: Call<ParkingInfo>, response: Response<ParkingInfo>) {
if (response.isSuccessful) {
response.body()?.data?.forEach {
Log.d("api", it.toString())
}
執行app後,從logcat可以看到有成功的將資料取得
參考
https://codelabs.developers.google.com/codelabs/kotlin-android-training-internet-data/