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

查看:543
本文介绍了在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之前返回mColor,因为它们是异步的.在此代码出现在MainActivity中之前,但我被建议起飞,但是现在当我尝试获取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调用可能尚未进行,因此您可以在API调用之前获得mColors值.

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. 使用实时数据,在viewmodel中,如果您不使用viewmodel,则在具有searchColorFromApi功能的class中声明它.

  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天全站免登陆