데이터가 들어오면 그 순서대로 처리가 되는 줄 알았는데 중구난방이었다.
.....생각 않고 코드를 짰다가 낭패를 봤다…
우선 예제로 돌릴 나의 삽질 코드부터 보자.
1. 순서대로 Retrofit을 생성해 돌릴 거니까, 반복문에 넣자!
for (i in 0 until artistList.size) {
Log.d("Retrofit","${i+1} / ${artistList.size} 번째 도는 중")
getArtistImg(artistNameList[i], i)
}
2. getArtistImge()는 이렇게 생겼다!
private fun getArtistImg(keyword: String, time: Int) {
val baseUrl = "https://dapi.kakao.com/v2/search/"
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service: SearchingService = retrofit.create(SearchingService::class.java)
val searchingMusic = service.searchArtistImg(auth = BuildConfig.KAKAO_IMAGE_API_AUTH, target = keyword, page = 1, size = 1)
searchingMusic.enqueue(object: Callback<ArtistImgData> {
override fun onResponse(
call: Call<ArtistImgData>,
response: Response<ArtistImgData>
) {
Log.d("Retrofit", "이미지 찾기 | 현재 키워드 : $keyword")
val body = response.body()
if (body != null) {
Log.d("Retrofit", "이미지 찾기 | 통신 성공")
artistList[time].imgUrl = body.documents[0].thumbnail_url
Log.d("Retrofit","${time+1}번째 잘 들어갔나.... ${artistList[time].imgUrl}")
if (time + 1 == artistList.size) {
setArtistAdapter(artistList)
}
}
else {
Log.d("Retrofit","이미지 찾기 | 바디 null")
}
}
override fun onFailure(call: Call<ArtistImgData>, t: Throwable) {
Log.d("Retrofit", "이미지 찾기 | 통신 실패", t)
}
})
}
로그를 찍어서 정말 순서대로 돌아가는지 확인해볼까?
왜 이렇게 멋대로 될까 싶었는데 생각해보니 바로 이게 비동기구나.
Thread {
searchingMusic.enqueue(object : Callback<ArtistImgData> {
override fun onResponse(
call: Call<ArtistImgData>,
response: Response<ArtistImgData>
) {
Log.d("Retrofit", "이미지 찾기 | 현재 키워드 : $keyword")
val body = response.body()
if (body != null) {
Log.d("Retrofit", "이미지 찾기 | 통신 성공")
artistList[time].imgUrl = body.documents[0].thumbnail_url
Log.d("Retrofit", "${time + 1}번째 잘 들어갔나.... ${artistList[time].imgUrl}")
if (time + 1 == artistList.size) {
setArtistAdapter(artistList)
}
} else {
Log.d("Retrofit", "이미지 찾기 | 바디 null")
}
}
override fun onFailure(call: Call<ArtistImgData>, t: Throwable) {
Log.d("Retrofit", "이미지 찾기 | 통신 실패", t)
}
})
}.start()
try {
Thread.sleep(50)
} catch (e: Exception) {
e.printStackTrace()
}
캡쳐는 하나 뿐이지만 여러 번 진행해도 동기로 잘 돌아가서 따로 추가하진 않았다.
그런데 하나 의문이 생긴다. 아무리 50밀리초와 같이 작은 시간을 딜레이 시킨다 해도 어쨌든 딜레이인데…… 문제가 생길 거 같다. 어떻게 처리하면 좋을까?
어차피 내가 동기로 실행시키길 원했던 이유는, 올바른 위치에서 어댑터를 세팅하기 위한 것이기 때문에 횟수를 따로 변수 선언해서 카운트하는 게 나을 거 같다.
var count = 0
private fun getArtistImg(keyword: String, time: Int) {
val baseUrl = "https://dapi.kakao.com/v2/search/"
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service: SearchingService = retrofit.create(SearchingService::class.java)
val searchingMusic = service.searchArtistImg(auth = BuildConfig.KAKAO_IMAGE_API_AUTH, target = keyword, page = 1, size = 1)
searchingMusic.enqueue(object : Callback<ArtistImgData> {
override fun onResponse(
call: Call<ArtistImgData>,
response: Response<ArtistImgData>
) {
Log.d("Retrofit", "이미지 찾기 | 현재 키워드 : $keyword")
val body = response.body()
if (body != null) {
Log.d("Retrofit", "이미지 찾기 | 통신 성공")
artistList[time].imgUrl = body.documents[0].thumbnail_url
count++
Log.d("Retrofit", "$count 번째 잘 들어갔나.... ${artistList[time].imgUrl}")
if (count == artistList.size) {
setArtistAdapter(artistList)
}
} else {
Log.d("Retrofit", "이미지 찾기 | 바디 null")
}
}
override fun onFailure(call: Call<ArtistImgData>, t: Throwable) {
Log.d("Retrofit", "이미지 찾기 | 통신 실패", t)
}
})
}
약간 제목에서 벗어났지만... 어쨌든 Retrofit 동기와 비동기에 대해 배웠으니까…!
겸사겸사 코루틴 코드도 살펴봤는데 정말 깔끔하다...
private fun getArtistImg(keyword: String, time: Int) {
val baseUrl = "https://dapi.kakao.com/v2/search/"
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service: SearchingService = retrofit.create(SearchingService::class.java)
val searchingMusic = service.searchArtistImg(
auth = BuildConfig.KAKAO_IMAGE_API_AUTH,
target = keyword,
page = 1,
size = 1
)
val response = searchingMusic.execute()
CoroutineScope(Dispatchers.Main).launch {
val body = response.body()
if (response.isSuccessful) {
if (body != null) {
Log.d("Retrofit", "이미지 찾기 | 통신 성공")
artistList[time].imgUrl = body.documents[0].thumbnail_url
Log.d("Retrofit", "${time + 1}번째 잘 들어갔나.... ${artistList[time].imgUrl}")
if (time + 1 == artistList.size) {
setArtistAdapter(artistList)
}
} else {
Log.d("Retrofit", "이미지 찾기 | 바디 null")
}
} else {
Log.d("Retrofit", "이미지 찾기 | 통신 실패")
}
}
}
저도 비슷한 상황인데 코드 한번만 봐주실 수 있나요 ㅠㅠ