Coroutine

gang_shik·2022년 7월 4일
0

프로젝트 Fit-In

목록 보기
9/9

Coroutine

  • Kotlin이 도입되면서 Thread로 비동기 처리를 한 것을 좀 더 작은 단위로써 처리할 수 있게 하는 Coroutine

  • 여기서 설명하는 Thread에 대한 Dispatchers와 Coroutine에 디테일한 개념에 대해서는 Kotlin 공식문서와 Android 공식문서 참고, 이 부분은 기존의 방식과 다르게 현재 Retrofit 적용에 있어서 어떻게 처리했는지 위주로 볼 것임

Retrofit에 Coroutine 도입

  • 먼저 API Interface를 보면 Coroutine 사용을 위해서 suspend로 선언을 함, 그리고 해당 함수를 비동기적으로 처리하고 호출하기 위해서
	@POST("/auth/login")
    suspend fun postSignIn(
        @Body body: RequestSignIn
    ): Response<ResponseToken>
  • 앞서 DI 패턴을 적용했기 때문에 별도의 Service에 대한 인스턴스 생성 없이 아래와 같이 Repository에서 suspend 함수로 만듬
suspend fun postSignIn(requestSignIn: RequestSignIn) = userService.postSignIn(requestSignIn)
  • 그리고 ViewModel에서 네트워크 요청을 보낼 때 UI Thread를 차단함, 그래서 새로운 코루틴을 만들고 요청을 함 모든 코루틴은 범위 내에서 실행해야하기 때문에 아래와 같이 ViewModelScope에서 실행을 함

  • 이 Scope는 ViewModel 범위 내에서 실행이 됨

fun onSignIn(view: View) {
        val request = RequestSignIn(email.value, password.value)
        viewModelScope.launch {
            val signin = userRepository.postSignIn(request)
            when (signin.isSuccessful) {
                true -> {
                    Log.e("token", "성공: " + signin.body()?.accessToken)
                    prefs.setAccessToken(signin.body()!!.accessToken)
                    prefs.setRefreshToken(signin.body()!!.refreshToken)
                    newsRepository.callNews()
                }
                else -> {
                    Log.e("실패", "error " + signin.message())
                }
            }
        }
        _eventSignIn.value = true
    }
  • 현재 위와 같은 방식으로 처리를 하여 정상적으로 처리됐지만 스레드 차단 상황과 main-safe 하게 하기 위해서 좀 더 Context 부분과 Dispatchers를 손봐야 할 부분이 있음

공식문서


추가

권장사항

  • 위의 문서상의 내용대로 권장사항으로써 Repository에서 Dispatchers를 추가해서 withContext로 처리한 부분 추가
	suspend fun callNews() = withContext(ioDispatcher) { newsService.callNews() }

    suspend fun getNewsList() = withContext(ioDispatcher) { newsService.getNewsList() }

    suspend fun getNews(newsId: Long) = withContext(ioDispatcher) { newsService.getNews(newsId) }
  • 추가로 변경 가능한 유형 노출하지 않은 부분에서 LiveData 일부를 아래와 같이 수정함
	private val _requestSignUp: MutableLiveData<RequestSignUp?> = MutableLiveData<RequestSignUp?>()
    val requestSignUp: LiveData<RequestSignUp?>
        get() = _requestSignUp

    fun getRequestSignUp(view: View) {
        val email: String = id.value + "@" + email.value
        val signUp = RequestSignUp(email, password.value, name.value)
        _requestSignUp.value = signUp
    }

    fun getRequestSignUpComplete() {
        _requestSignUp.value = null
    }
profile
측정할 수 없으면 관리할 수 없고, 관리할 수 없으면 개선시킬 수도 없다

0개의 댓글