코딩기록

[안드로이드 스튜디오] retrofit2 동기처리 본문

백엔드/Kotlin

[안드로이드 스튜디오] retrofit2 동기처리

빌럽스 2024. 7. 6. 20:05

 

1. 문제발생

농구장 위치 공유 앱 개발 중, 다음과 같이 전역변수의 값을 retrofit을 통해 설정하려고 하였으나 전역변수에 값이 저장되지 않았다.

var hoop = intent.getSerializableExtra("hoop") as Hoop

val retrofit = Retrofit.Builder().baseUrl(BuildConfig.API_URL)
    .addConverterFactory(GsonConverterFactory.create()).build()
val service = retrofit.create(RetrofitService::class.java)

service.getHoop(hoop.id)
    .enqueue(object : Callback<ResponseDto<Hoop>> {
        override fun onResponse(
            call: Call<ResponseDto<Hoop>>,
            response: Response<ResponseDto<Hoop>>
        ) {
            hoop = response.body()!!.data
        }

        override fun onFailure(call: Call<ResponseDto<Hoop>>, t: Throwable) {
            Toast.makeText(
                this@PopupActivity,
                "농구장 불러오기에 실패했습니다. 잠시 후 다시 시도해 주세요.",
                Toast.LENGTH_LONG
            ).show()
        }
    })

 

2. 원인

원인을 확인해 보니 사용하고 있던 retrofit의 <.enqueue> 메서드는 비동기 방식으로 정보를 가져오기 때문에 발생한 문제였다. 즉, api로 정보를 다 가져오기 전에 그 다음 코드가 실행되어 버린 것이다.

 

동기 방식의 <.execute>를 사용하면 정보가 저장될 수 있을 것이다.

 

3. 트러블슈팅

그러나 .execute를 사용했더니 NetworkOnMainThreadException가 발생했다.

원인은 Network API를 MainActivity에서 직접 호출했기 때문이다. 이것을 금지해 놓은 이유를 확인해 보니 MainActivity에서 Network관련 작업을 직접 실행할 경우 MainThread가 멈추는 현상이 발생할 수 있기 때문에 이를 금지시켜 놓은 것이었다.

 

-> 다음과 같이 새로운 쓰레드를 구동시킴으로써 .execute 메서드를 사용할 수 있었다.

Thread {
    hoop = service.getHoop(hoop.id).execute().body()!!.data
    binding.name.text = hoop.name
    binding.hoopCount.text = if (hoop.hoopCount == 0) "(정보없음)" else hoop.hoopCount.toString()
    binding.floorType.text = hoop.floorType.krName
    binding.light.text = hoop.light.krName
    binding.freeState.text = hoop.freeState.krName
    binding.standardState.text = hoop.standardState.krName
    binding.commentBtn.text = "추가정보 : 이 농구장의 댓글 " + hoop.commentCount + "개"

    // 댓글
    binding.commentBtn.setOnClickListener {
        this.finish()
        val intent = Intent(this@PopupActivity, CommentPopupActivity::class.java)
        intent.putExtra("hoop", hoop)
        startActivity(intent)
    }

    // 업데이트
    binding.updateBtn.setOnClickListener {
        this.finish()
        val intent = Intent(this@PopupActivity, UpdatePopupActivity::class.java)
        intent.putExtra("hoop", hoop)
        startActivity(intent)
    }

    // 신고
    binding.reportBtn.setOnClickListener {
        this.finish()
        val intent = Intent(this@PopupActivity, ReportPopupActivity::class.java)
        intent.putExtra("hoop", hoop)
        startActivity(intent)
    }

}.start()

 

'백엔드 > Kotlin' 카테고리의 다른 글

코틀린 물음표(?)와 느낌표(!) 차이  (0) 2024.05.19