일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- DiffUtil.ItemCallback
- getChangePayload
- exoplayer cache
- ListAdapter DiffUtil
- doc2vec
- ListAdapter
- android custom view
- kotlin list
- llm
- 유튜브
- video caching
- map
- 시행착오
- kotlin collection
- ktor client
- 안드로이드
- 독서
- android exoplayer
- android
- 스피너
- Python
- ExoPlayer
- Zsh
- AWS EC2
- list map
- android ktor
- build with ai
- FastAPI
- ChatGPT
- ktor api call
- Today
- Total
버튼 수집상
[안드로이드] Retrofit 대신 Ktor로 Api 호출해보기 - 1 본문
배경
KMM (Kotlin Multiplatform Mobile) 이 여기저기서 많이 언급되고 있다.
줄곧 XML을 쓰다가 마침 Compose 프로젝트를 할 기회가 생겼다.
이 기회에 Ktor도 써보면 어떨까 생각이 들어서 간단하게 써보았다.
Philipp Lackner 의 아래 영상을 참고했다.
그런데 예제에서 쓰는 HttpClient.get() 함수의 시그니처가 달랐다.
예제에선 io.ktor:ktor-client-core-jvm:1.6.3에서 아래 함수 호출.
/**
* Executes a [HttpClient] GET request, with the specified [scheme], [host], [port], [path] and [body].
* And allows to further configure the request, using a [block] receiving an [HttpRequestBuilder].
*
* Tries to receive a specific type [T], if fails, an exception is thrown.
*/
public suspend inline fun <reified T> HttpClient.get(
scheme: String = "http",
host: String = "localhost",
port: Int = DEFAULT_PORT,
path: String = "/",
body: Any = EmptyContent,
block: HttpRequestBuilder.() -> Unit = {}
): T = request {
url(scheme, host, port, path)
method = HttpMethod.Get
this.body = body
apply(block)
}
타입을 리턴하기 때문에 아래와 같이 호출부를 정의할 수 있다.
override suspend fun getPosts(): List<PostResponse> {
return client.get { url(HttpRoutes.POSTS) }
}
그런데 io.ktor:ktor-client-core-jvm:2.3.6 버전의 HttpClient.get()은 HttpResponse를 리턴한다.
/**
* Executes an [HttpClient]'s GET request with the parameters configured in [builder].
*
* Learn more from [Making requests](https://ktor.io/docs/request.html).
*/
public suspend inline fun HttpClient.get(builder: HttpRequestBuilder): HttpResponse {
builder.method = HttpMethod.Get
return request(builder)
}
그래서 받아온 HttpResponse의 body()를 호출해서 json으로 파싱해줘야한다.
아래 코드를 참고했다.
https://github.com/ktorio/ktor-documentation/tree/2.3.7/codeSnippets/snippets/client-json-kotlinx
gradle.properties
ktor_version=2.3.6
build.gradle.kts(:app)
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.serialization")
}
//...
dependencies {
// 다른 라이브러리 생략
// ktor
val ktor_version: String by project
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-android:$ktor_version")
implementation("io.ktor:ktor-client-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-client-logging:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
}
플러그인 선언 잊지 말 것.
대부분의 예제에서 버전을 스네이크 케이스로 적던데 kotlin 린트 때문에 노란줄이 뜬다..
PostApiService (HttpClient 정의)
interface PostApiService {
suspend fun getPosts(): List<PostResponse>
companion object {
fun create(): PostApiServiceImpl {
return PostApiServiceImpl(
client = HttpClient(Android) {
expectSuccess = true
// plugins
install(ContentNegotiation) {
json()
}
install(ResponseObserver) {
onResponse { response ->
Log.i("logger", "${response.status.value}")
}
}
install(DefaultRequest) {
header(HttpHeaders.ContentType, ContentType.Application.Json)
}
}
)
}
}
}
PostResponse
import kotlinx.serialization.Serializable
@Serializable
data class PostResponse(
val id: Int,
val userId: Int,
val title: String,
val body: String
)
PostApiServiceImpl
class PostApiServiceImpl(
private val client: HttpClient,
) : PostApiService {
override suspend fun getPosts(): List<PostResponse> {
return client.get {
url(HttpRoutes.POSTS)
}.body()
}
}
MainActivity (Compose)
class MainActivity : ComponentActivity() {
private val service = PostApiService.create()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val posts = produceState<List<PostResponse>>(
initialValue = emptyList(),
producer = {
value = service.getPosts()
}
)
CommunityTheme {
// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
LazyColumn {
items(posts.value) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(text = it.title ?: "", fontSize = 20.sp)
Spacer(modifier = Modifier.height(4.dp))
Text(text = it.body ?: "", fontSize = 15.sp)
}
}
}
}
}
}
}
}
이러면 영상 속 예제대로 api를 호출할 수 있다.
추신
ktor-server 라이브러리도 제공되는데, API를 안드로이드 앱으로 만드는 이유가 있나?
멀티플랫폼 지원이니까 웹에서 띄운다는 느낌이겠지?
'TIL - 안드로이드' 카테고리의 다른 글
[안드로이드] 모서리가 둥근 뷰파인더 만들기 rounded square transparent mask for zxing barcode reader UI (0) | 2023.12.14 |
---|---|
[안드로이드] Retrofit 대신 Ktor로 Api 호출해보기 - 2 (0) | 2023.12.11 |
[안드로이드] TextView 원하는 글자만 남기고 말줄임표 보여주기 Custom Ellipsis (1) | 2023.12.07 |
[안드로이드] ListAdapter DiffUtil 제대로 쓰기 - 4 (0) | 2023.11.30 |
[안드로이드] Process란 (0) | 2023.11.08 |