I have an app that has bottom Navigation bar which implemented with compose navigation. This bottom navigation bar navigate between different screen (each screen is a composable function).
I want to execute an enquiry using ApolloGraphQl Client inside home screen. However, if I want to execute the enquiry:
fun HomeScreen() {
Text(text = "Home")
val response = apolloClient.query(LaunchListQuery()).execute()
Log.d("LaunchList", "Success ${response.data}")
}
I get this error
Suspend function 'execute' should be called only from a coroutine or another suspend function
in ApollographQl tutorial, they used Fragments which has its own lifecycle, but I want to use composable functions and searching online didn't give me a clear answer.
I tried @oliverbj answer as:
@Preview
@Composable
fun HomeScreen() {
val coroutineScope = rememberCoroutineScope()
val getLaunchOnClick: () -> Unit = {
coroutineScope.launch {
val response = async(Dispatchers.IO) {
apolloClient.query(LaunchListQuery()).execute()
}
Log.d("LaunchList", "Success ${response.await().data}")
}
}
Text(text = "Home")
Button(onClick = getLaunchOnClick) {
Text("Launch")
}
}
and it worked thanks @oliverbj also thanks for @heyheyhey
CodePudding user response:
To fix the error you are getting, you can use the withContext function to execute your Apollo GraphQL query within a coroutine. Here's how you can do that:
@Composable
fun HomeScreen() {
val coroutineScope = rememberCoroutineScope()
val getLaunchOnClick: () -> Unit = {
coroutineScope.launch {
val response = withContext(Dispatchers.IO) {
apolloClient.query(LaunchListQuery()).execute()
}
Log.d("LaunchList", "Success ${response.data}")
}
}
Text(text = "Home")
}
The withContext
function lets you specify which coroutine dispatcher to use, in this case Dispatchers.IO
, which is the recommended dispatcher for performing blocking IO operations such as making network requests.
You can also use the async function to simplify the code even further:
@Composable
fun HomeScreen() {
val coroutineScope = rememberCoroutineScope()
val getLaunchOnClick: () -> Unit = {
coroutineScope.launch {
val response = async(Dispatchers.IO) {
apolloClient.query(LaunchListQuery()).execute()
}
Log.d("LaunchList", "Success ${response.await().data}")
}
}
Text(text = "Home")
}
The async
function returns a Deferred object, which you can await to get the result of the suspended computation.