在 Kotlin 中回调后返回一个值 [英] Returning a value after callback in Kotlin

查看:26
本文介绍了在 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 callasynchronous,所以只要你调用 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

  1. 使用 callback这在您当前的设置中几乎不需要修改,但第二个选项比这更可取. 使用callback 你的函数应该是这样的.

  1. Use callback, this will require little modification in your current setup, but the 2nd option is preferable over this. Using callback 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)

  1. 使用Live Data,声明如下field 在你的 viewmodel 中,如果你没有使用 viewmodel 然后在 class 中声明它有 searchColorFromApi 函数.

  1. Use Live Data, declare following field in your viewmodel, if you are not using viewmodel then declare it in the class which has searchColorFromApi 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆