在 Kotlin 中回调后返回一个值 [英] Returning a value after callback in Kotlin
问题描述
如何在 kotlin 回调后返回值,我尝试使用 Thread.sleep 但它不起作用
How can I return a value after a callback in kotlin, I tried using Thread.sleep but it doesn't work
fun searchColorFromAPI(): Colors {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
if (serviceResponse != null) {
mColors = serviceResponse
}
else {
//buildToast(getString(R.string.null_response))
}
}
else {
//buildToast(getString(R.string.response_unsuccessful))
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
/* buildToast(getString(R.string.error_calling_service))
Log.e(TAG, t?.message)*/
}
})
return mColors
}
总是在 onFailure 或 onResponse 之前返回 mColors,因为它们是异步的.在这段代码在 MainActivity 之前,但我被建议起飞,但现在当我尝试 get mColors 时,我在 onResponse 执行前后得到空值,请我仍在学习 Kotlin 和 Android.
Always, the mColors is returned before the onFailure or onResponse because they're asynchronous. Before this code was in MainActivity but I was advised to take off, but now when I try get mColors I get the empty value before and after the onResponse is executed, please I'm still learning Kotlin and Android.
推荐答案
你的问题源于 Retrofit
call
是 asynchronous
,所以只要你调用 searchColorFromAPI
它就会返回你 mColors
但是 API
调用可能还没有进行,所以你之前得到了 mColors 值API 调用.
Your problem stems from the fact that Retrofit
call
is asynchronous
, so as soon as you call searchColorFromAPI
it returns you mColors
but the API
call may not have been made yet, so you get the mColors value before API call.
要解决这个问题,你可以这样做
To solve this issue, you can do
使用
callback
,这在您当前的设置中几乎不需要修改,但第二个选项比这更可取. 使用callback
你的函数应该是这样的.
Use
callback
, this will require little modification in your current setup, but the 2nd option is preferable over this. Usingcallback
your function should look like this.
/* Now instead of returning a value, your function takes a function (named callback)
as parameter. when your api call finishes, you can call the callback function and
pass the api response.
*/
fun searchColorFromAPI(callback: (Colors?) -> Unit) {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
/** pass API response to callback */
callback(serviceResponse)
}
else {
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
callback(null)
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
callback(null)
}
})
}
并在您的 activity
中声明一个 function
如下.
And in your activity
declare a function
as follows.
// This function will be called when your api call finishes
// and it will give you the api response
fun apiCallback(colors: Colors?){
if(colors == null){
// API Call failed
}
else{
// use colors as returned by API
}
}
现在调用 searchColorFromApi
应该是这样的
And now call to searchColorFromApi
should look like this
searchColorFromApi(apiCallback)
使用Live Data,声明如下
field
在你的viewmodel
中,如果你没有使用viewmodel
然后在class
中声明它有searchColorFromApi
函数.
Use Live Data, declare following
field
in yourviewmodel
, if you are not usingviewmodel
then declare it in theclass
which hassearchColorFromApi
function.
var colors: MutableLiveData<Colors> = MutableLiveData()
并修改您的 searchColorFromAPI
函数如下
and modify your searchColorFromAPI
function as follows
fun searchColorFromAPI() {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
if (serviceResponse != null) {
colors.postValue(response.body)
}
}
else {
colors.postValue(null)
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
colors.postValue(null)
}
})
}
并在您的 activity
中执行以下操作
and in your activity
do following
fun setupObservers(){
yourApiCallingClass.colors.observe(this, Observer {
// this code is called when ever value of color field changes
})
}
这篇关于在 Kotlin 中回调后返回一个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!