본문 바로가기

프로그램/Android

코루틴을 이용한 비동기 처리방법

반응형

여태까지 개발을 모바일앱 개발을 하면서 특정 타이밍 때문에 delay를 별도로 준적이 많다.

 

예제로 사용할 앱 첫로딩시에 첫번째 fragment statck을 가져와야할때가 예시라고 할수있다.

 

그럴때마다 delay를 별도로 줘서 데이터를 가져왔다.

lifecycleScope.launch {
    delay(700)
    val current = navHostFragment.childFragmentManager.fragments.firstOrNull()

}

 

 

저렇게 딜레이를 주지 않으면 앱이 시작할때나 특정타이밍에 null인 케이스가 종종 발생한다.

 

이렇게 딜레이를 주고 값을 받아오는건 좋지 않은 코드이다. 불필요하게 기다릴수도 또는 저 타이밍안에 못들어올수도 있으니,

 

해당부분과 같은 비동기처리를 하는방법중 하나는 아래와 같다.

private suspend fun waitFirstFragment(navHostFragment: Fragment): Fragment {
    return suspendCancellableCoroutine { continuation ->
        val fragmentManager = navHostFragment.childFragmentManager
        val existingFragment = fragmentManager.fragments.firstOrNull()

        if (existingFragment != null) { //프래그먼트가 null인지 체크하여 null이 아니면 fragment를 전달
            continuation.resume(existingFragment)
        } else {
            //없다면 fragment callback을 추가하여 데이터를 전달받음
            val callback = object : FragmentManager.FragmentLifecycleCallbacks() {
                override fun onFragmentAttached(
                    fm: FragmentManager,
                    fragment: Fragment,
                    context: Context
                ) {
                    fragmentManager.unregisterFragmentLifecycleCallbacks(this)
                    continuation.resume(fragment)
                }
            }

            //전달받을때까지 기다릴수 있도록 처리
            fragmentManager.registerFragmentLifecycleCallbacks(callback, true)
            continuation.invokeOnCancellation { //완료되면 콜백 제거
                fragmentManager.unregisterFragmentLifecycleCallbacks(callback)
            }
        }
    }
}

 

위의 코드가 callback으로 결과값을 받을수있는 형식이다

 

suspendCancellableCoroutine을 이용한다면 아주 쉽게 비동기처리를 해결할수있다.

 

continuation.resume(existingFragment)

 

데이터의 값을 전달하는건 resume으로 데이터를 전달 해야한다.

 

그리고 위의 예제와 같이 필수적으로 완료된 후 처리를 해야하는 무엇인가가 있다면 invokeOnCancellation을 이용해서 처리해야한다.

 

해당 예제는 callback을 제거해야 하기에 invokeOnCancellation 를 이용하였다.

continuation.invokeOnCancellation { //완료되면 콜백 제거
    fragmentManager.unregisterFragmentLifecycleCallbacks(callback)
}

 

반응형