Project
09_mvvm : Network communication using retrofit - Search User Test
DevGoni
2021. 2. 23. 16:38
728x90
IRetrofit_Service
에서 Coroutine
으로 비동기 처리를 하기위해서 suspend
키워드를 추가
@GET(API.SEARCH_USERS)
suspend fun searchUsers(@Query("query") searchTerm : String) : JsonElement
// 사용자 검색 서비스
Network와 통신해서 수신받은 data를 파싱하고 data class
타입의 ArrayList
담아 Bundle
을 이용해 전달하기 위해서 User Class를 생성
data class User(var username: String, var profile_image: String) :Serializable
// Serializable을 상속받아 직렬화가 가능하도록 한다.
API에 사용자 검색에 대한 요청
//RetrofitManager.kt
//사용자검색 api 호출
fun searchUsers(searchTerm: String?, completion: (RESPONSE_STATE, ArrayList<User>?) -> Unit) {
val term = searchTerm.let { it } ?: ""
mScope.launch {
var parsedUserDataArray = ArrayList<User>()
val job = launch(Dispatchers.IO) {
val call =
iretrofitService?.searchUsers(searchTerm = term).let { it } ?: return@launch
val body = call.asJsonObject
val results = body.getAsJsonArray("results")
val total = body.get("total").asInt
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${total}")
if (total != 0) {
// JsonArray result[] 내부의 JsonObject를 하나씩 받아 반복 수행
results.forEach { resultItem ->
val resultItemObject = resultItem.asJsonObject // get object
val username = resultItemObject.get("username").asString // user -> username
val profile_image =
resultItemObject.get("profile_image").asJsonObject.get("small").asString
// object -> create_at
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${username}")
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${profile_image}")
val userItem = User(
username = username,
profile_image = profile_image,
)
parsedUserDataArray.add(userItem)
//ArrayList에 Photo 타입의 데이터를 추가가
}
}
}
job.join()
if(job.isCompleted){
completion(RESPONSE_STATE.OK, parsedUserDataArray)
}
}
}
Button 클릭 시 enum class
의 SEARCH_TYPE 상수 값에 따라 사진, 사용자 검색 API를 호출하고 고차함수를 사용해 요청의 결과를 반환
// HomeActivty.kt
// SEARCH 버튼 이벤트
binding.include.searchButton.setOnClickListener {
Log.d(Constants.TAG, "HomeActivity SEARCH 버튼 클릭 - currentSearchType : ${currentSearchType}")
handleSearchButton() // 프로그래스바 활성화
//검색 api 호출
val userSearchInput = binding.searchEditText.text.toString()
if(currentSearchType == SEARCH_TYPE.PHOTO){
Log.d(Constants.TAG, "HomeActivity api 사진 검색 요청")
//검색 api 호출
RetrofitManager.instance.searchPhotos(searchTerm = userSearchInput, completion = {
response_state, responsePhotoArrayList ->
// responsePhotoArrayList : RetrofitManager.kt에서 Parsing한 Photo타입의 ArrayList
when(response_state){
RESPONSE_STATE.OK -> {
Log.d(Constants.TAG, "HomeActivity api 호출 성공 : ${responsePhotoArrayList?.size}")
val intent = Intent(this, CollectionActivity::class.java)
val bundle = Bundle()
bundle.putSerializable("photo_array_list", responsePhotoArrayList)
//bundle은 Parcelable 객체를 상속받아 구현된 직렬화 class로, bundle 객체는 내부적으로 HashMap을 사용하며,
// Parcelable로 구현되어 있어 간단한 데이터 전달에 유용하다.
// putSerializable()을 이용하면 객체가 Serialzable을 상속받고 있다면 객체를 보낼 수 있다.
// 직렬화 : 객체를 바이트 스트림으로 바꾸어, 객체에 저장된 데이터를 스트림에 쓰기위해 연속적인 serial 데이터로 변환
intent.putExtra("array_bundle", bundle)
//intent.putExtra()로 해당 번들을 넣는다.
intent.putExtra("searchTerm", userSearchInput)
// 사용자가 입력한 입력값(AppBar의 Title로 사용)
startActivity(intent)
}
RESPONSE_STATE.FAIL -> {
Log.d(Constants.TAG, "HomeActivity api 호출 실패 : ${responsePhotoArrayList}")
}
RESPONSE_STATE.NONE -> {
Toast.makeText(this, getString(R.string.No_search_results), Toast.LENGTH_SHORT).show()
binding.searchEditText.setText("")
//검색 결과가 없을 때만 검색창 초기화
}
}
handleSearchButton()
// 프로그래스바 비활성화
})
}else if(currentSearchType == SEARCH_TYPE.USER){
Log.d(Constants.TAG, "HomeActivity api 사용자 검색 요청")
RetrofitManager.instance.searchUsers(searchTerm = userSearchInput, completion = {
response_state, responseUserArrayList ->
// responsePhotoArrayList : RetrofitManager.kt에서 Parsing한 Photo타입의 ArrayList
when(response_state){
RESPONSE_STATE.OK -> {
Log.d(Constants.TAG, "HomeActivity api 호출 성공 : ${responseUserArrayList?.size}")
/*
val intent = Intent(this, CollectionActivity::class.java)
val bundle = Bundle()
bundle.putSerializable("user_array_list", responseUserArrayList)
//bundle은 Parcelable 객체를 상속받아 구현된 직렬화 class로, bundle 객체는 내부적으로 HashMap을 사용하며,
// Parcelable로 구현되어 있어 간단한 데이터 전달에 유용하다.
// putSerializable()을 이용하면 객체가 Serialzable을 상속받고 있다면 객체를 보낼 수 있다.
// 직렬화 : 객체를 바이트 스트림으로 바꾸어, 객체에 저장된 데이터를 스트림에 쓰기위해 연속적인 serial 데이터로 변환
intent.putExtra("array_bundle", bundle)
//intent.putExtra()로 해당 번들을 넣는다.
intent.putExtra("searchTerm", userSearchInput)
// 사용자가 입력한 입력값(AppBar의 Title로 사용)
startActivity(intent)
*/
}
RESPONSE_STATE.FAIL -> {
Log.d(Constants.TAG, "HomeActivity api 호출 실패 : ${responseUserArrayList}")
}
RESPONSE_STATE.NONE -> {
Toast.makeText(this, getString(R.string.No_search_results), Toast.LENGTH_SHORT).show()
binding.searchEditText.setText("")
//검색 결과가 없을 때만 검색창 초기화
}
}
handleSearchButton()
// 프로그래스바 비활성화
})
}
}