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
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
:
In ViewModel
we can use viewModelScope
to launch a coroutine:
viewModelScope.launch { ... }
It attached to the lifecycle of Activity/Fragment
and cancels launched coroutines when they destroyed.
Activity/Fragment
we can use the following extension properties to launch a coroutine:
lifecycleScope.launch {}
, lifecycle.coroutineScope.launch {}
, viewLifecycleOwner.lifecycleScope.launch {}
(applicable in Fragments
).