테스트 할 Empty Activity 를 생성합니다. (이제 생성 단계는 생략)
이름은 RestApiActivity 로 하고, Source Language 는 Kotlin
class RestApiActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rest_api)
}
}
기본적으로 이렇게 코드가 나오는데, 아래와 같이 ViewBinding 으로 변경합니다.
class RestApiActivity : AppCompatActivity() {
private lateinit var binding: ActivityRestApiBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRestApiBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
}
API
사용할 api 는 무료로 open 되어있는 휴일 검색 API 입니다. 가입 필요 없습니다~
https://date.nager.at/api/v2/publicholidays/{year}/{locale}
url 뒤에 year과 locale 만 입력하면 결과가 나옵니다.
Retrofit2
Retrofit은 안드로이드 및 Kotlin에서 네트워크 요청을 쉽게 처리하기 위한 라이브러리입니다.
RESTful API와의 통신을 위해 매우 인기 있는 라이브러리로, 네트워크 요청을 선언적인 방식으로 작성할 수 있도록 도와줍니다.
최신 버전은 여기 에서 확인이 가능합니다.
라이브러리 추가
build.gradle 에 dependencies 에 아래 두개 항목을 추가합니다.
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
그리고 Sync Now 를 눌러줍니다.
Manifest
인터넷 사용 권한을 추가합니다.
<uses-permission android:name="android.permission.INTERNET"/>
DataClass
api 를 호출하면 반환되는 형식이 JSON 이기 때문에, 이것을 data class 로 변환하도록
형식에 맞는 data class 를 생성합니다.
우선 리턴되는 형식은 다음과 같습니다.
[
{
"date":"2023-01-01",
"localName":"새해",
"name":"New Year's Day",
"countryCode":"KR",
"fixed":true,
"global":true,
"counties":null,
"launchYear":null,
"type":"Public"
},
...생략
]
package를 먼저 생성하고 그 안에 class를 만듭니다.
package 이름은 models
models 페키지 아래에 Kotlin Class/File 생성 > Data class
이름은 PublicHolidays
PublicHolidays.kt
data class PublicHolidays(
@SerializedName("date") val date: Date,
@SerializedName("localName") val dateName: String,
@SerializedName("name") val engName: String,
@SerializedName("countryCode") val locale: String,
@SerializedName("fixed") val fixed: Boolean,
@SerializedName("global") val global: Boolean,
@SerializedName("counties") val counties: String?,
@SerializedName("launchYear") val launchYear: String?,
@SerializedName("type") val type: String
)
SerializeName 은 api 서버에서 받아온 json 의 key 이름입니다. val 뒤에있는 프로퍼티에 값을 전달합니다.
이름은 달라도 됩니다.
Retrofit Service Interface
package com.example.test01.interfaces
import com.example.test01.models.PublicHolidays
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path
interface DateApiService {
@GET("/api/v2/publicholidays/{year}/{locale}")
fun getHolidays(
@Path("year") year: String,
@Path("locale") locale: String
): Call<List<PublicHolidays>>
}
우선 models와 같은 level로 interfaces 라는 package 를 만들고 그 안에 생성합니다.
만약에 path variable이 아니라 /api/v2/publicholidays?year=2023&locale=KR 이었다면
@Query("year") year:String
이런식으로 Query 로 입력해야합니다.
사용하기
준비가 길었습니다.. 이제 사용할 차례네요.
다시 RestApiActivity.kt 로 와서 retrofit 을 선언하고 객체를 생성합니다.
package com.example.test01
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.test01.databinding.ActivityLifeBinding
import com.example.test01.databinding.ActivityRestApiBinding
import com.example.test01.interfaces.DateApiService
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class RestApiActivity : AppCompatActivity() {
// 여기부터
val retrofit = Retrofit.Builder()
.baseUrl("https://date.nager.at/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val dateApiService = retrofit.create(DateApiService::class.java)
// 여기까지
private lateinit var binding: ActivityRestApiBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRestApiBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
}
그리고 버튼을 하나 추가하고, 클릭했을 때 dateApiService 를 사용하도록 해보겠습니다.
버튼은 layout file (activity_rest_api.xml) 에서 추가하시고, 버튼 텍스트와 id 를 입력한 후
(저는 rest_get_button 로 id 를 지정했습니다. 그래서 아래 코드에 binding.restGetButton 으로 사용)
binding.restGetButton.setOnClickListener {
dateApiService.getHolidays("2023", "KR")
.enqueue(object: Callback<List<PublicHolidays>> {
override fun onResponse(call: Call<List<PublicHolidays>>, response: Response<List<PublicHolidays>>) {
if(response.isSuccessful.not()){
return
}
response.body()?.let{
Log.d("OK", it.toString())
it.forEachIndexed { index, publicHolidays ->
Log.d("DATA", "[$index] date = ${publicHolidays.date}, name = ${publicHolidays.dateName}")
}
} ?: run {
Log.d("NG", "body is null")
}
}
override fun onFailure(call: Call<List<PublicHolidays>>, t: Throwable) {
Log.e("ERROR", t.toString())
Toast.makeText(applicationContext, t.toString(), Toast.LENGTH_LONG).show()
}
})
}
MainActivity 에서 RestApiActivity 로 넘어오는 것은..
MainActivity 에서 버튼 하나 만들고 클릭했을 때, 아래 줄 코드를 실행하면 됩니다.
startActivity(Intent(this, RestApiActivity::class.java))
앱을 실행하고, RestApiActivity 로 넘어와서 restGetButton 버튼을 누르면 결과는..
D/DATA: [0] date = Sun Jan 01 00:00:00 GMT+09:00 2023, name = 새해
D/DATA: [1] date = Sat Jan 21 00:00:00 GMT+09:00 2023, name = 설날
D/DATA: [2] date = Mon Jan 23 00:00:00 GMT+09:00 2023, name = 설날
D/DATA: [3] date = Tue Jan 24 00:00:00 GMT+09:00 2023, name = 설날
D/DATA: [4] date = Wed Mar 01 00:00:00 GMT+09:00 2023, name = 3·1절
D/DATA: [5] date = Fri May 05 00:00:00 GMT+09:00 2023, name = 어린이날
D/DATA: [6] date = Sat May 27 00:00:00 GMT+09:00 2023, name = 부처님 오신 날
D/DATA: [7] date = Tue Jun 06 00:00:00 GMT+09:00 2023, name = 현충일
D/DATA: [8] date = Tue Aug 15 00:00:00 GMT+09:00 2023, name = 광복절
D/DATA: [9] date = Thu Sep 28 00:00:00 GMT+09:00 2023, name = 추석
D/DATA: [10] date = Fri Sep 29 00:00:00 GMT+09:00 2023, name = 추석
D/DATA: [11] date = Sat Sep 30 00:00:00 GMT+09:00 2023, name = 추석
D/DATA: [12] date = Tue Oct 03 00:00:00 GMT+09:00 2023, name = 개천절
D/DATA: [13] date = Mon Oct 09 00:00:00 GMT+09:00 2023, name = 한글날
D/DATA: [14] date = Mon Dec 25 00:00:00 GMT+09:00 2023, name = 크리스마스
이렇게 나옵니다.. 잘 되네요.
파이썬이랑 비교되네요. 단계가 너무 많아...
'Android' 카테고리의 다른 글
[Kotlin] Fragment 에서 상위 Activity Method 호출하기 (0) | 2023.07.28 |
---|---|
[Kotlin] Fragment 사용하기 (0) | 2023.07.28 |
[Kotlin] apply, with, let, ?: 사용하기 (0) | 2023.07.25 |
[Kotlin] 리니어 레이아웃(LinearLayout) 예제 (0) | 2023.07.25 |
[Kotlin] Android Java 와 Kotlin 몇가지 문법 비교 (0) | 2023.07.24 |
댓글