https://jsonplaceholder.typicode.com/albums?userId=3
api주소에 ?userId=3
이라는 쿼리문을 붙여 특정 값으로 정렬된 데이터를 볼 수 있다.
retrofit으로 쿼리문을 통해 특정 데이터를 가져오려면
AlbumService.kt
interface AlbumService {
//https://jsonplaceholder.typicode.com = base url /albums = End Point
@GET("/albums")
suspend fun getAlbums() : Response<Albums>
@GET("/albums")
suspend fun getSortedAlbums(@Query("userId") userId: Int) : Response<Albums>
}
와 같이 @Query
애너테이션을 붙여서 userId를 인자로 받을 수 있다.
MainActivity.kt
val responseLiveData : LiveData<Response<Albums>> = liveData{
val response = retService.getSortedAlbums(3)
emit(response)
}
https://api.visitjeju.net/vsjApi/contents/searchList?apiKey=qwzi0ndhnnvrqi8r&locale=kr&category=c4
위와 같이 apiKey, locale, category의 여러가지 쿼리가 &로 묶여 Get을 해야하는 경우도 있다 이럴 때는 단순히 여러개의 쿼리문을 이어주면 된다.
interface JejuService {
@GET("/vsjApi/contents/searchList")
suspend fun getFoodList(
@Query("apiKey") apiKey: String,
@Query("locale") locale: String? = "kr",
@Query("category") category: String? = "c4"
) : Response<FoodList>
jsonplaceholder api에서는 추가적으로 id 경로를 입력하여 그 id 에 해당하는 album item 1개를 받아올 수도 있다.
https://jsonplaceholder.typicode.com/albums/3
이를 받아올 수 있는 코드를 AlbumService에 추가적으로 작성해준다.
@GET("/albums/{id}")
suspend fun getAlbum(@Path(value = "id") albumId : Int) : Response<AlbumsItem>
데이터를 albums 가 아닌 단 하나의 오브젝트인 albumsItem을 가져오므로 main에서 liveData를 새로 정의해줘야 한다.
val pathResponse : LiveData<Response<AlbumsItem>> = liveData {
val response = retService.getAlbum(3)
emit(response)
}
pathResponse.observe(this, Observer {
val title = it.body()?.title
Toast.makeText(applicationContext,title,Toast.LENGTH_SHORT).show()
})
id = 3에 해당하는 album title이 toast 메시지로 띄워진다.
HttpLoggingInterceptor 는 OKHttp에서 지원하는 라이브러리로, post, get, 등 http 통신 메서드가 실행이 정상적으로 되어있는지 로그로 확인할 수 있도록 해준다.
class RetrofitInstance {
companion object{
val BASE_URL = "https://jsonplaceholder.typicode.com"
val interceptor = HttpLoggingInterceptor().apply {
this.level = HttpLoggingInterceptor.Level.BODY//얼만큼 확인할 지
}
val client = OkHttpClient.Builder().apply {
this.addInterceptor(interceptor)
}.build()
fun getRetrofitInstance() : Retrofit{
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.build()
}
}
}
retrofit instance를 위와 같이 바꿔주었다.
HttpLoggingInterceptor().apply로 interceptor을 가져오고, Level.BODY
로 내가 확인할 json의 범위를 지정해준다.
그리고 client 변수를 만들어 builder에 interceptro을 넣어주고, RetrofitBuilder안에 .client(client)
로 넣어준다.
실행하면
로그에서 json 파일이 잘 전달되는지와
Http status code(200이면 성공적으로 실행됨을 의미)을 볼 수 있다.
인터넷 환경에 따라서 데이터를 주고 받는 시간이 다름을 고려하여 타이머를 세팅할수도 있다.
이 역시 client에서 지정해주는데,
val client = OkHttpClient.Builder().apply {
this.addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(20,TimeUnit.SECONDS)
.writeTimeout(25,TimeUnit.SECONDS)
}.build()
앞선 코드를 위와 같이 connect, read, write에 따른 타이머를 설정하였다.
아무래도 GET과 더불어서 POST로 서버에 데이터를 넘기거나 수정하는 작업을 가장 많이 하지 않을까 싶다.
@POST("/albums")
suspend fun uploadAlbum(@Body album : AlbumsItem) : Response<AlbumsItem>
Post 메서드를 추가하여 albums array의 body에 AlbumsItem 하나를 인자로 담아보낸다.
private fun uploadAlbum(){
val album = AlbumsItem(0,"My Title",3)
val postResponse : LiveData<Response<AlbumsItem>> = liveData {
val response = retService.uploadAlbum(album)
emit(response)
}
postResponse.observe(this, Observer {
val receivedAlbumsItem = it.body()
val result = " " + "Album Title : ${receivedAlbumsItem?.title}" + "\n"+
" " + "Album Id : ${receivedAlbumsItem?.id}" + "\n"+
" " + "User Id : ${receivedAlbumsItem?.userId}" + "\n\n\n"
binding.textView.text=result
})
}
main에서 uploadAlbum 함수를 만들어 실행해주면, 화면에 내가 입력한 Title, Id(100개가 만들어져 있어 101로 저장됨),User Id 를 볼 수 있다.