Appearance
从互联网获取数据
实例代码:https://github.com/google-developer-training/basic-android-kotlin-compose-training-mars-photos
- 添加权限 manifests/AndroidManifest.xml 文件
xml
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
....
</application>
- 添加依赖
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
- network/MarsApiService.kt
java
package com.example.marsphotos.network
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
private const val BASE_URL = "https://api.thecatapi.com/"
// 配置 Json 实例
val json = Json {
ignoreUnknownKeys = true // 忽略未知字段
}
// 配置 Retrofit 实例
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
// 定义 API 服务接口
interface MarsApiService {
@GET("v1/images/search?limit=10")
suspend fun getPhotos(): List<MarsPhoto>
}
- network/MarsApi.kt
java
package com.example.marsphotos.network
object MarsApi {
val retrofitService : MarsApiService by lazy {
retrofit.create(MarsApiService::class.java)
}
}
- network/MarsPhoto
java
package com.example.marsphotos.network
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class MarsPhoto(
val id: String,
// @SerialName("url") val imageUrl: String,
val url: String,
val width: Int,
val height: Int
)
- ui/screens/MarsViewModel.kt 调用
java
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.marsphotos.ui.screens
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.marsphotos.network.MarsApi
import kotlinx.coroutines.launch
import java.io.IOException
sealed interface MarsUiState {
data class Success(val photos: String) : MarsUiState
object Error : MarsUiState
object Loading : MarsUiState
}
class MarsViewModel : ViewModel() {
/** The mutable State that stores the status of the most recent request */
// var marsUiState: String by mutableStateOf("")
// private set
var marsUiState: MarsUiState by mutableStateOf(MarsUiState.Loading)
private set
/**
* 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] [MutableList].
*/
fun getMarsPhotos() {
// marsUiState = "Set the Mars API status response here!"
viewModelScope.launch {
marsUiState = try {
val listResult = MarsApi.retrofitService.getPhotos()
MarsUiState.Success("Success: ${listResult.size} Mars photos retrieved")
} catch (e: IOException) {
MarsUiState.Error
}
}
}
}