Reputation: 225
Iam new to jetpack compose, and trying to figure it out how it works. i am having problem, that i want to call a method inside my @Composable function which is in another class.
This is my main activity code
package com.example.bohubrihiwithjetpack
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import com.example.bohubrihiwithjetpack.retrofit.RetrofitClient
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Response
import java.lang.Exception
import javax.security.auth.callback.Callback
class MainActivity : ComponentActivity() {
private val weatherAPI = "rNCnpnQge4Il62hiTcLVX6FAr8IPG7oW"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
composable()
}
}
fun getRegionsHttp() {
RetrofitClient.getInstance().getApi()
?.getRegions(weatherAPI)
?.enqueue(object : retrofit2.Callback<ResponseBody> {
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
if (response.isSuccessful) {
val successFul = response.body()?.string()
Toast.makeText(this@MainActivity, successFul, Toast.LENGTH_SHORT).show()
} else {
try {
val errorDetect = response.errorBody()?.string()
val error = errorDetect
Toast.makeText(this@MainActivity, error, Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Toast.makeText(this@MainActivity, "something wrong", Toast.LENGTH_SHORT)
.show()
}
}
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
Toast.makeText(this@MainActivity, t.message, Toast.LENGTH_SHORT).show()
}
})
}
}
Now i want to call the getRegionsHttp method inside the below @Composable function.
package com.example.bohubrihiwithjetpack
import androidx.compose.runtime.Composable
@Composable
fun composable() {
}
How do i do that?
Upvotes: 3
Views: 9214
Reputation: 390
Just in case you decided to call api from composable function like that, I would like to highlight that this Api is going to be called an unexpected number of times because of the recomposition; therefore, you need to actually determine why would you do that. Calling an Api should be event based or maybe at the page loading time. As an example to load the API at the start you might find it here
Also Composables should be depending on states and actions to be passed from outside, and to avoid doing logic inside it as it is a declarative UI which should only describe the UI; however, to answer your question you might check the below code.
class MainActivity : ComponentActivity() {
private val weatherAPI = "rNCnpnQge4Il62hiTcLVX6FAr8IPG7oW"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
composable { getRegionsHttp() }
}
}
@Composable
fun composable(regionsHttp:() ->Unit) {}
Upvotes: 2
Reputation: 149
Use viewModel
class myViewModel: ViewModel() {
fun getRegionsHttp(resp: (Response<ResponseBody>) -> Unit) {
viewModelScope.launch {
RetrofitClient.getInstance().getApi()
?.getRegions(weatherAPI)
?.enqueue(object : retrofit2.Callback<ResponseBody> {
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
resp.invoke(response)
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
}
})
}
}
}
In your composable function
@Composable
fun composable(viewModel: myViewModel) {
val context = LocalContext.current
viewModel.getRegionsHttp() {
if (it.isSuccessful) {
Toast.makeText(context, response.body()?.string(), Toast.LENGTH_SHORT)
}
}
}
if you using navigation you can pass your code like this
composable(viewModel())
Upvotes: 4