안녕하세요 오늘 작성할 내용은 통신 라이브러리 Retrofit2이 무엇인지에 대해 알아보고 영화진흥위원회 API를 활용하여 데이터를 요청하고 받아오는 예제를 만들어 보겠습니다!!
레트로핏이란?
- Square사에서 만든 HTTP 통신 라이브러리입니다.
- OkHttp 라이브러리를 기반으로 만들어졌습니다.
레트로핏 장점
- AsyncTask를 사용하여 OkHttp에 비해서 빠른 속도를 지원합니다.
- Annotation을 사용하여 가독성이 좋습니다.
- 동기 / 비동기를 지원합니다.
Retrofit2로 영화진흥위원회 API 사용하기
1. 라이브러리 의존성, 매니패스트 인터넷 권한 추가
https://github.com/square/retrofit
위 링크에 접속해 최신버전을 확인해 앱 수준의 그래들에 의존성을 추가합니다. 글 작성 당시 최신버전은 2.11.0이 최신버전이라 2.11.0 버전으로 진행하겠습니다.
build.gradle.kts (앱 수준)
// Retrofit2
implementation ("com.squareup.retrofit2:retrofit:2.11.0")
implementation( "com.squareup.retrofit2:converter-gson:2.11.0")
Manifast 파일에 인터넷 permission을 추가합니다.
AndroidManifast.xml
<uses-permission android:name="android.permission.INTERNET"/>
2. 모델 클래스를 만들기 위해 먼저 영화진흥위원회 API를 확인합니다.
먼저 API를 사용하기 위해 영화진흥위원회 홈페이지에 접속해 회원가입을 진행합니다.
https://www.kobis.or.kr/kobisopenapi/homepg/main/main.do
주간 박스오피스 데이터가 필요하기 때문에 주간 박스오피스 API 서비스로 들어가겠습니다.
요청 URL을 먼저 확인하고 요청 파라미터에 어떤 데이터가 필요한지 확인합니다.
위 파라미터를 기반으로 Interface를 만들어 주겠습니다.
ApiInterface.kt
package com.example.retrofit2_example
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiInterface {
@GET("boxoffice/searchWeeklyBoxOfficeList.json")
fun getMovieList(
@Query("key") key : String,
@Query("targetDt") targetDt : String,
@Query("weekGb") weekGb : String
): Call<ModelClass>
}
Response를 받아줄 Model 클래스도 만들어주겠습니다.
ModelClass.kt
package com.example.retrofit2_example
data class ModelClass(
var boxOfficeResult: BoxOfficeResult
) {
data class BoxOfficeResult(
var boxofficeType: String,
var showRange: String,
var weeklyBoxOfficeList: List<WeeklyBoxOffice>,
var yearWeekTime: String
) {
data class WeeklyBoxOffice(
var audiAcc: String,
var audiChange: String,
var audiCnt: String,
var audiInten: String,
var movieCd: String,
var movieNm: String,
var openDt: String,
var rank: String,
var rankInten: String,
var rankOldAndNew: String,
var rnum: String,
var salesAcc: String,
var salesAmt: String,
var salesChange: String,
var salesInten: String,
var salesShare: String,
var scrnCnt: String,
var showCnt: String
)
}
}
위 클래스는 영화진흥위원회 API에 응답 파라미터를 기준으로 만들어야 합니다.
모델 클래스와 요청 인터페이스를 만들었으니 한번 요청을 보내보도록 하겠습니다.
MainActivity.kt
package com.example.retrofit2_example
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private val BASE_URL = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/"
private val key = "영화진흥위원회에서 발급받는 키"
private lateinit var retrofit: Retrofit
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
getMovie()
}
private fun init(){
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
private fun getMovie(){
retrofit.create(ApiInterface::class.java).getMovieList(key,"20240420","0").enqueue(
object : Callback<ModelClass>{
override fun onResponse(call: Call<ModelClass>, response: Response<ModelClass>) {
if(response.isSuccessful) {
Log.d(TAG, "onResponse: ${response.body()?.boxOfficeResult}")
}
}
override fun onFailure(p0: Call<ModelClass>, p1: Throwable) {
Log.d(TAG, "요청 실패 : $p1")
}
}
)
}
}
위 코드를 실행 시켰을때 아래와 같은 결과를 확인 할 수 있습니다.
2024-04-26 20:48:08.090 6445-6445 MainActivity com.example.retrofit2_example D onResponse: BoxOfficeResult(boxofficeType=주간 박스오피스, showRange=20240415~20240421, weeklyBoxOfficeList=[WeeklyBoxOffice(audiAcc=1248303, audiChange=-57.6, audiCnt=370571, audiInten=-504361, movieCd=20236614, movieNm=쿵푸팬더4, openDt=2024-04-10, rank=1, rankInten=0, rankOldAndNew=OLD, rnum=1, salesAcc=11681285845, salesAmt=3443394942, salesChange=-58.1, salesInten=-4767261961, salesShare=37.7, scrnCnt=1533, showCnt=34193), WeeklyBoxOffice(audiAcc=11785099, audiChange=-38.6, audiCnt=171009, audiInten=-107358, movieCd=20234675, movieNm=파묘, openDt=2024-02-22, rank=2, rankInten=0, rankOldAndNew=OLD, rnum=2, salesAcc=113914246413, salesAmt=1689456118, salesChange=-38.6, salesInten=-1062648304, salesShare=18.5, scrnCnt=1053, showCnt=18717), WeeklyBoxOffice(audiAcc=386880, audiChange=-43.1, audiCnt=65289, audiInten=-49441, movieCd=20231677, movieNm=남은 인생 10년, openDt=2023-05-24, rank=3, rankInten=1, rankOldAndNew=OLD, rnum=3, salesAcc=3952099130, salesAmt=652200364, salesChange=-43.2, salesInten=-496126546, salesShare=7.1, scrnCnt=529, showCnt=7203), WeeklyBoxOffice(audiAcc=963871, audiChange=-58.5, audiCnt=48168, audiInten=-67812, movieCd=20231041, movieNm=댓글부대, openDt=2024-03-27, rank=4, rankInten=-1, rankOldAndNew=OLD, rnum=4, salesAcc=9158023810, salesAmt=470920646, salesChange=-58.9, salesInten=-673545496, salesShare=5.2, scrnCnt=631, showCnt=7791), WeeklyBoxOffice(audiAcc=36960, audiChange=19671.0, audiCnt=36774, audiInten=36588, movieCd=20248466, movieNm=고스트버스터즈: 오싹한 뉴욕, openDt=2024-04-17, rank=5, rankInten=59, rankOldAndNew=OLD, rnum=5, salesAcc=348915020, salesAmt=347241020, salesChange=20643.2, salesInten=345567020, salesShare=3.8, scrnCnt=671, showCnt=7567), WeeklyBoxOffice(audiAcc=174052, audiChange=-52.7, audiCnt=28406, audiInten=-31634, movieCd=20247673, movieNm=오멘: 저주의 시작, openDt=2024-04-03, rank=6, rankInten=-1, rankOldAndNew=OLD, rnum=6, salesAcc=1789740877, salesAmt=295875931, salesChange=-52.5, salesInten=-326674475, salesShare=3.2, scrnCnt=427, showCnt=3877), WeeklyBoxOffice(audiAcc=28253, audiChange=100.0, audiCnt=28253, audiInten=28253, movieCd=20228797, movieNm=범죄도시4, openDt=2024-04-24, rank=7, rankInten=0, rankOldAndNew=NEW, rnum=7, salesAcc=326042800, salesAmt=326042800, salesChange=100.0, salesInten=326042800, salesShare=3.6, scrnCnt=24, showCnt=163), WeeklyBoxOffice(audiAcc=1987130, audiChange=-23.6, audiCnt=20303, audiInten=-6286, movieCd=20236295, movieNm=듄: 파트2, openDt=2024-02-28, rank=8, rankInten=0, rankOldAndNew=OLD, rnum=8, salesAcc=23287956313, salesAmt=261810792, salesChange=-20.8, salesInten=-68768771, salesShare=2.9, scrnCnt=188, showCnt=1572), WeeklyBoxOffice(audiAcc=506726, audiChange=-64.4, audiCnt=14929, audiInten=-27055, movieCd=20248496, movieNm=고질라 X 콩: 뉴 엠파이어, openDt=2024-03-27, rank=9, rankInten=-3, rankOldAndNew=OLD, rnum=9, salesAcc=5076739231, salesAmt=144696681, salesChange=-64.7, salesInten=-264954213, salesShare=1.6, scrnCnt=303, showCnt=2522), WeeklyBoxOffice(audiAcc=16986, audiChange=546.3, audiCnt=14710, audiInten=12434, movieCd=20235613, movieNm=스턴트맨, openDt=2024-05-01, rank=10, rankInten=14, rankOldAndNew=OLD, rnum=10, salesAcc=157866000, salesAmt=137382000, salesChange=570.7, salesInten=116898000, salesShare=1.5, scrnCnt=35, showCnt=71)], yearWeekTime=202416)
이제 받아온 데이터를 리사이클러뷰에 띄어주고 마치겠습니다.
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
<TextView
android:id="@+id/rank"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1위" />
<TextView
android:id="@+id/movieNm"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="영화이름" />
<TextView
android:id="@+id/openDt"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="YYYY-MM-DD" />
</LinearLayout>
Adapters.kt
package com.example.retrofit2_example
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class Adapters (var itemList: List<ModelClass.BoxOfficeResult.WeeklyBoxOffice>) : RecyclerView.Adapter<Adapters.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Log.d("ddd", "onBindViewHolder: ${itemList[position]}")
holder.tvRank.text = itemList[position].rank
holder.tvNm.text = itemList[position].movieNm
holder.tvDt.text = itemList[position].openDt
}
override fun getItemCount(): Int {
return itemList.count()
}
fun setList(list : List<ModelClass.BoxOfficeResult.WeeklyBoxOffice>){
itemList = list
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvNm = itemView.findViewById<TextView>(R.id.movieNm)
val tvRank = itemView.findViewById<TextView>(R.id.rank)
val tvDt = itemView.findViewById<TextView>(R.id.openDt)
}
}
MainActivity.kt
package com.example.retrofit2_example
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private val BASE_URL = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/"
private val key = "영화진흥위원회에서 발급한 키"
private lateinit var retrofit: Retrofit
private lateinit var recyclerView: RecyclerView
private lateinit var list : List<ModelClass.BoxOfficeResult.WeeklyBoxOffice>
private lateinit var adapter : Adapters
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
getMovie()
}
private fun init(){
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
list = ArrayList()
adapter = Adapters(list)
recyclerView = findViewById(R.id.recyclerview)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
}
private fun getMovie(){
retrofit.create(ApiInterface::class.java).getMovieList(key,"20240420","0").enqueue(
object : Callback<ModelClass>{
override fun onResponse(call: Call<ModelClass>, response: Response<ModelClass>) {
if(response.isSuccessful) {
if(response.body()?.boxOfficeResult?.weeklyBoxOfficeList != null){
list = response.body()?.boxOfficeResult?.weeklyBoxOfficeList!!
adapter.setList(list)
}
}
}
override fun onFailure(p0: Call<ModelClass>, p1: Throwable) {
Log.d(TAG, "요청 실패 : $p1")
}
}
)
}
}
위 코드를 실행 한 후 결과 화면
이상 레트로핏에 대해 작성해봤는데요. 레트로핏을 공부하는분들에게 도움이 되었으면 합니다. 감사합니다
'Android' 카테고리의 다른 글
안드로이드 Compose란 + 예제 (0) | 2024.03.05 |
---|---|
안드로이드 DataBinding 사용 예제 (0) | 2024.03.04 |
안드로이드 ROOM 사용법 + 예제 (0) | 2024.03.03 |
Hilt 란? (0) | 2024.02.06 |
WebRTC 란? (2) | 2023.08.08 |
댓글