2023年10月27日 星期五

【Android Studio】使用 Retrofit 程式庫與後端通訊


簡介

  • Retrofit 程式庫是一個用戶端程式庫,可讓應用程式向 REST 網路服務發出要求。
    • 一般的網路服務使用 REST 架構。提供 REST 架構的網路服務稱為「符合 REST 樣式」的服務。符合 REST 樣式的網路服務,均使用標準網路元件和通訊協定建構而成。
    • 使用轉換工具向 Retrofit 告知該如何處理傳送至網路服務的資料,以及從網路服務傳回的資料。舉例來說,ScalarsConverter 轉換工具會將網路服務資料視為 String 或其他原始檔案。

新增 Retrofit 依附元件

開啟模組層級 Gradle 檔案 build.gradle (Module: MarsPhots.app)。
在 dependencies 區段中,為 Retrofit 程式庫新增以下幾行:
// Retrofit
implementation "com.squareup.retrofit2:retrofit:2.9.0"
// Retrofit with Scalar Converter
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"

若要搭配 Moshi 將 JSON 字串轉為 Kotlin 物件,則將上述改為:
// Moshi
implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'


用例 

使用 Scalars (將網路服務資料視為 String)

在 MarsApiService.kt 中:

private const val BASE_URL = "https://android-kotlin-fun-mars-server.appspot.com/" //網路服務基準URI

private val retrofit = Retrofit.Builder() //新增 Retrofit 建構工具
    .addConverterFactory(ScalarsConverterFactory.create()) //添加支援字串和其他原始類型的轉換工廠 (注意此處使用的是Scalars,需搭配其依附元件使用)
    .baseUrl(BASE_URL) //新增網路服務的基準 URI
    .build() //建立 Retrofit 物件

interface MarsApiService {
    @GET("photos")  //向 Retrofit 表明此為 GET 要求,並指定該網路服務方法的端點/photos
    suspend fun getPhotos(): String
}

object MarsApi {
    // 使用 retrofit.create() 方法初始化 retrofitService 變數
    val retrofitService: MarsApiService by lazy { retrofit.create(MarsApiService::class.java) }
}

在 OverviewViewModel.kt 的 class OverviewViewModel 中 :

    private fun getMarsPhotos() {
        _status.value = "Set the Mars API status response here!"
        viewModelScope.launch {
            try{
                val listResult = MarsApi.retrofitService.getPhotos()
                _status.value = listResult //顯示收到的後端伺服器結果
            } catch (e: Exception) {
                _status.value = "Failure: ${e.message}"
            }
        }
    }

使用 Moshi (將 JSON 轉為 Kotlin 物件) 


在 MarsPhoto .kt 中: 

/*
    Moshi 剖析 JSON 時,會根據名稱比對鍵,並在資料物件中填入適當的值。
 */
data class MarsPhoto (
    val id: String,
    @Json(name = "img_src") val imgSrcUrl: String
)

在 MarsApiService.kt 中:

private const val BASE_URL = "https://android-kotlin-fun-mars-server.appspot.com/" //網路服務基準URI

private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder() //新增 Retrofit 建構工具
    .addConverterFactory(MoshiConverterFactory.create(moshi)) //添加支援字串和其他原始類型的轉換工廠
    .baseUrl(BASE_URL) //新增網路服務的基準 URI
    .build() //建立 Retrofit 物件

interface MarsApiService {
    @GET("photos")  //向 Retrofit 表明此為 GET 要求,並指定該網路服務方法的端點/photos
    suspend fun getPhotos(): List<MarsPhoto>
}

object MarsApi {
    // 使用 retrofit.create() 方法初始化 retrofitService 變數
    val retrofitService: MarsApiService by lazy { retrofit.create(MarsApiService::class.java) }
}

關於最後一句:

在 OverviewViewModel.kt 的 class OverviewViewModel 中 :

class OverviewViewModel : ViewModel() {

    // The internal MutableLiveData that stores the status of the most recent request
    private val _status = MutableLiveData<String>()

    // The external immutable LiveData for the request status
    val status: LiveData<String> = _status
    /**
     * Call getMarsPhotos() on init so we can display status immediately.
     */
    init {
        getMarsPhotos()
    }

    /**
     * Gets Mars photos information from the Mars API Retrofit service and updates the
     * [MarsPhoto] [List] [LiveData].
     */
    private fun getMarsPhotos() {
        _status.value = "Set the Mars API status response here!"
        viewModelScope.launch {
            try{
                val listResult = MarsApi.retrofitService.getPhotos()
                _status.value = "Success: ${listResult.size} Mars photos retrieved" //顯示收到的後端伺服器結果
            } catch (e: Exception) {
                _status.value = "Failure: ${e.message}"
            }
        }
    }
}
在 viewmodel 建立後呼叫getMarsPhotos()

資料來源



0 comments:

張貼留言