V predošlých lekciách sme používali sealed triedy na reprezentáciu stavov. Teraz si ukážeme, ako ich použiť v kombinácii s HTTP klientom na elegantné spracovanie odpovedí:
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.Serializable
import kotlinx.coroutines.runBlocking
@Serializable
data class Todo(val id: Int, val title: String, val completed: Boolean)
sealed class NetworkResult {
data object Loading : NetworkResult()
data class Success(val data: List<Todo>) : NetworkResult()
data class Error(val message: String) : NetworkResult()
}
suspend fun fetchTodos(client: HttpClient): NetworkResult {
return try {
val response = client.get("https://jsonplaceholder.typicode.com/todos")
if (response.status == HttpStatusCode.OK) {
val todos = response.body<List<Todo>>()
NetworkResult.Success(todos)
} else {
NetworkResult.Error("Server vratil: ${response.status}")
}
} catch (e: Exception) {
NetworkResult.Error("Chyba siete: ${e.message}")
}
}
fun handleResult(result: NetworkResult) {
when (result) {
is NetworkResult.Loading -> println("Nacitavam data...")
is NetworkResult.Success -> {
println("Nacitaných ${result.data.size} todo:")
result.data.take(3).forEach { println(" - ${it.title}") }
}
is NetworkResult.Error -> println("Chyba: ${result.message}")
}
}
fun main() = runBlocking {
val client = HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
val result = fetchTodos(client)
handleResult(result)
client.close()
}
Tento vzor (sealed class + when) je veľmi častý v Android vývoji pre spracovanie stavov UI.
Vytvor sealed triedu výsledku požiadavky so stavmi načítavanie, úspech a chyba.
Napíš suspend funkciu, ktorá pri úspešnej odpovedi vráti dáta a pri chybe stav chyby.
Spracuj výsledok úplným when a pri úspechu vypíš počet načítaných objektov.