며칠 전 업로드한 Asynctask 방식 대신 Retrofit2 이라는 Square사에서 제공하는 오픈소스 라이브러리를 사용하여 구현해보았다. 처음 사용해 본 오픈소스라 약간 낯설었지만, 조금 익숙해지니 기존 방식보단 더 편한거 같기도 ,,?
xml 파싱에 SimpleXmlConverterFactory 를 사용했지만, 이것도 .. deprecated 되었다고 하니 다른 분들은 JAXBConverter 를 사용하시는 걸 추천 !!
내가 생각하기에 REST API는 요청 값이랑 받아오는 리턴 형식만 잘 맞추면 큰 무리 없이 기능 완성이 가능한 거 같다.
꼭꼭 사용하고자 하는 api의 요청 변수 값을 제대로 넣어줘야 사용이 가능하니 체크 하기
오늘 목표 : 위치 기준으로 전국 약국 조회하기
[ 요청시 반환되는 xml 파일 형식 ]
1. permission과 dependencies 설정하기
retrofit2과 converter를 버전을 맞춰서 넣기
또한 통신을 위해서 Manifest에 internet permission을 넣어주기
2. Retrofit API 설정하기 ( interface )
interface RetrofitAPI{ // data를 얻기 위한 retrofitAPI
@GET("getParmacyLcinfoInqire?")
fun getPharmacy(@Query("ServiceKey") ServiceKey:String,
@Query("WGS84_LON") WGS84_LON:Double,
@Query("WGS84_LAT") WGS84_LAT:Double)
: Call<SearchResponseWrapper>
}
@Query로 요청할 때 필요한 변수들의 이름을 넣어주면 된다.
3. 값을 받는 POJO 클래스 정의하기
@Root(name="response")
class SearchResponseWrapper @JvmOverloads constructor(
@field:Element(name="header")
var header:GetHeader? =null,
@field:Element(name="body")
var body:SearchResponse? = null
)
@Root(name="header")
class GetHeader @JvmOverloads constructor(
@field:Element(name="resultCode")
var resultCode:String ="",
@field:Element(name="resultMsg")
var resultMsg:String = ""
)
@Root(name= "body")
class SearchResponse @JvmOverloads constructor(
@field:Element(name="items")
var items:ResponseItme? =null,
@field:Element(name="numOfRows")
var numOfRows:String? =null,
@field:Element(name="pageNo")
var pageNo:String? = null,
@field:Element(name = "totalCount")
var totalCount:String? = null
)
@Root(name="items")
class ResponseItme @JvmOverloads constructor(
@field:ElementList(inline = true)
var item:List<Item>?=null
)
@Root(name="item")
class Item @JvmOverloads constructor(
@field: Element(name = "cnt")
var cnt:String ="",
@field: Element(name = "distance")
var distance:String ="",
@field: Element(name = "dutyAddr")
var dutyAddr:String ="",
@field: Element(name = "dutyDiv")
var dutyDiv:String ="",
@field: Element(name = "dutyDivName")
var dutyDivName:String ="",
@field: Element(name = "dutyFax",required = false)
var dutyFax:String ="",
@field: Element(name = "dutyName")
var dutyName:String= "",
@field: Element(name = "dutyTel1")
var dutyTel1:String = "",
@field: Element(name = "endTime")
var endTime:String ="",
@field: Element(name = "hpid")
var hpid:String ="",
@field: Element(name = "latitude")
var latitude:String ="",
@field: Element(name = "longitude")
var longitude:String ="",
@field: Element(name = "rnum")
var rnum:String ="",
@field: Element(name = "startTime")
var startTime:String =""
)
json 의 POJO 클래스 예시는 많았지만, xml 예시는 거의 없어서 내가 직접 올린다. 정말 많은 구글링 끝에 발견 ㅠㅠ
xml은 Element (name = 변수 이름 ) 을 넣어주면 된다. 이때 변수 이름은 반환 받은 변수의 이름과 정확히 일치해야 하며 반환 되는 부분의 변수를 모두 넣어줘야 제대로 값을 받을 수 있다 !!!!
반환되는 item 마다 어떤 변수는 들어있고, 없고 하는 경우가 있다. 이런 경우에 required = false를 넣어주면 된다.
4. Builder 설정
fun setRetrofitInit() {
retrofit = Retrofit.Builder()
.baseUrl("http://apis.data.go.kr/B552657/ErmctInsttInfoInqireService/")
.addConverterFactory(SimpleXmlConverterFactory.create())
//.client(createOkHttpClient())
.build()
retrofitService = retrofit.create(RetrofitAPI::class.java)
}
나는 따로 함수를 만들어서 Bulider를 설정했다.
baseUrl부분은 바뀌지 않는 url까지 넣어주면 된다.
5. Client 객체 만들고 통신 & 응답 처리
fun callProduct() {
retrofitService.getPharmacy(ServiceKey,log!!,lan!!)
.enqueue(object : retrofit2.Callback<SearchResponseWrapper> {
override fun onResponse(
call: Call<SearchResponseWrapper>,
response: retrofit2.Response<SearchResponseWrapper>
) {
val body = response.body()
Log.d("data", body)
}
override fun onFailure(call: Call<SearchResponseWrapper>, t: Throwable) {
Log.d("fail", t.message.toString())
}
})
}
제대로 데이터를 긁어온 것을 확인 할 수 있을 것이다.
참고로 나는 xml 형식으로 파싱 받은 데이터 처리 부분에 고민하다가 아무리 생각해도 모르겠어서 그냥 반환 데이터를 json으로 변환한 후 필요한 정보만 arrayList에 넣어서 fragment에 띄워줬다. 제대로 작동되긴 하지만 코드에 자신이 없어서 그 부분은 일단 제외하고 업로드를 했다.
-> 제가 했던 방식 외에 더 좋은 방식의 자료가 있다면 추천 부탁드립니다 !
[결과]
현재 위치를 기반으로 알아서 가장 가까운 약국부터 순서대로 데이터가 들어온다. 파일 데이터 였으면 추가로 위도 경도 별로 거리 계산 함수를 만든 뒤 정렬해서 데이터를 뿌려줬어야 하지만, 알아서 거리 순서대로 정렬되어 데이터가 들어오니 정말 편리 한거 같답
전체 코드는 어플이 완성되면 깃허브에 업로드 할 예정이다
'Android' 카테고리의 다른 글
[Android] 공공데이터 오픈 API를 활용한 의약품 검색 App (0) | 2021.02.11 |
---|---|
[Android/Kotlin] 공공데이터 오픈 API Gson 파싱 - AsyncTask (0) | 2020.10.31 |
[Android] 공공데이터 오픈 API를 활용한 서울시 대피소 App (0) | 2020.10.31 |
[Android] 공공데이터 오픈 API- http 네트워크 통신 오류 (0) | 2020.10.29 |