ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • suspend fun
    개발/안드로이드 2021. 7. 22. 20:00

    코틀린에서 추가된 suspend 함수는 Coroutine 내에서만 실행 가능한 함수다. 블로그 글마다 suspend 함수에 대해서 각각 정의가 다른데 나는 suspend 함수를 Coroutine Context를 갖고 있는 함수 정도로 정의하고 싶다.

     

    간단한 사용법 

     

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            CoroutineScope(Dispatchers.Main).launch {
                val sum = suspendSum(1, 2) // no compile error  
                Log.d("suspend sum", sum.toString())
            }
            
            suspendSum(1, 2) // compile error
        }
    
        private suspend fun suspendSum(a: Int, b: Int) : Int {
            return a + b
        }
    }
    
    29210-29210/com.kwony.mylib D/suspend sum: 3

     

    suspend 함수는 Coroutine Job 내에서 일반 함수처럼 호출이 가능하다. 그런데 외부에서는 부모의 Coroutine Context를 받지 않기 때문에 일반 함수처럼 호출이 안된다. Couroutine Context를 가지고 있는 점을 이용해서 아래 코드처럼 바꿀 수 있다. 

     

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            CoroutineScope(Dispatchers.Main).launch {
                val sum = suspendSum(1, 2)
                Log.d("mainactivity coroutine", Thread.currentThread().name)
                Log.d("mainactivity coroutine", sum.toString())
            }
        }
    
        private suspend fun suspendSum(a: Int, b: Int) : Int = withContext(Dispatchers.IO) {
            Log.d("mainactivity suspend", Thread.currentThread().name)
            return@withContext a + b
        }
        
        
    mainactivity suspend: DefaultDispatcher-worker-2
    mainactivity coroutine: main
    mainactivity coroutine: 3

     

    위 코드를 보면 suspend 함수 body가 withContext로 싸여져 있는 것을 볼 수 있다. 아래 코드를 실행 할 때는 withContext 함수를 이용해 쓰레드를 바꿔서 실행할 수 있다. suspend + withContext를 활용하면 특정 함수에 대해서 실행 쓰레드를 정해 Main 함수를 건드리지 않고 안전하게 실행할 수 있게 된다.

     

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            CoroutineScope(Dispatchers.Main).launch {
                val sum = suspendSum(1, 2)
                Log.d("mainsuspendsum", sum.toString())
            }
        }
    
        private suspend fun suspendSum(a: Int, b: Int) : Int = withContext(Dispatchers.IO) {
            val deferredSum = async { a + b }
            val deferredZero = async { 0}
            return@withContext deferredSum.await() + deferredZero.await()
        }

     

    상황에 따라서 내부에 async 로 새로운 job을 생성해서 실행이 가능하다. suspend 함수는 내부가 Coroutine과 완전히 동일하다고 봐도 된다. 코드를 좀더 간결하게 쓸 수 있는 도구가 될 것 같다.

    '개발 > 안드로이드' 카테고리의 다른 글

    ListAdapter, DiffUtil  (0) 2021.08.20
    Coroutine + Retrofit | Coroutine + Room  (0) 2021.07.22
    Single, Maybe, Completable  (0) 2021.07.04
    Serializable 과 Parcelable  (0) 2021.06.19
    kotlin lateinit, lazy by  (0) 2021.06.05

    댓글

Designed by Tistory.