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
The syntax of a suspending function is similar to that of a regular function except for the addition of the suspend keyword. It can take a parameter and have a return type. However, suspending functions can only be invoked by another suspending function or within a coroutine.
With coroutines, it just suspends and gives the library a continuation with the instruction "Once you've got this data, just send it to the resume function". Then the thread can go do other things. Once the data is there, the thread will be used to resume from the point where the coroutine was suspended.
Coroutines can suspend themselves, and the dispatcher is responsible for resuming them. To specify where the coroutines should run, Kotlin provides three dispatchers that you can use: Dispatchers. Main - Use this dispatcher to run a coroutine on the main Android thread.
Answer: a. You should not use them for any foreground task.
Suspend function should be called only from coroutine. That means you need to use a coroutine builder, e.g. launch
. 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 BETTER 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
).Looks like the most elegant way to do it as of July 2019, is the one described here:
import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch class Activity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super... lifecycleScope.launch { val result = callGetApi() onResult(result) } } }
Don't forget to add the correponding lib:
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha02"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With