Search code examples
androidkotlinkotlin-coroutinescoroutinecoroutinescope

Suspend function 'callGetApi' should be called only from a coroutine or another suspend function


I am calling suspended function from onCreate(...)

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    ...
    callGetApi()
}

and the suspended function is:-

suspend fun callGetApi() {....}

But the error shows up Suspend function 'callGetApi' should be called only from a coroutine or another suspend function


Solution

  • Suspend function should be called only from a coroutine.

    That means to call a suspend function you need to use a coroutine builder, e.g. launch, async or runBlocking(recommended to use only in unit tests). For example:

    class Activity : AppCompatActivity(), CoroutineScope {
        private var job: Job = Job()
    
        override val coroutineContext: CoroutineContext
            get() = Dispatchers.Main + job
    
        override fun onDestroy() {
            super.onDestroy()
            job.cancel()
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            launch {
                val result =  callGetApi()
                onResult(result) // onResult is called on the main thread
            }
        }
    
        suspend fun callGetApi(): String {...}
    
        fun onResult(result: String) {...}
    }
    

    To use Dispatchers.Main in Android add dependency to the app's build.gradle file:

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
    

    The MOST RECENT APPROACH would be to use extension properties in ViewModel and Activity/Fragment:

    It attached to the lifecycle of Activity/Fragment and cancels launched coroutines when they destroyed.