在 Kotlin 中,在回调后返回一个值

3

我该如何在Kotlin中在回调后返回一个值?我尝试使用Thread.sleep,但它不起作用。

   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中,但我被建议移除它,但现在当我尝试获取mColors时,在onResponse执行前后都会得到空值,请注意我仍在学习Kotlin和Android。


Kotlin的lambda函数对于回调很有用。请查看此答案以获取从函数回调的示例。[https://stackoverflow.com/a/59942825/12688463] - Patibandha Parth
2个回答

4
你遇到的问题源于Retrofit call异步的,所以当你调用searchColorFromAPI时,它会立即返回mColors,但API调用可能还没有被执行,因此你会在API调用前获取到mColors的值。
为了解决这个问题,你可以进行以下操作:
  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
// 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的方法应该像这样

searchColorFromApi(apiCallback)
  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函数修改为以下内容。

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 中,请执行以下操作
  fun setupObservers(){
       yourApiCallingClass.colors.observe(this, Observer {
        // this code is called when ever value of color field changes
       })
   }

-1
  1. 你可以使用实时数据,该数据在回调接收后更新,同样的实时数据由调用方片段/活动观察。

  2. 您可以使用协程从具有异步调用的函数返回值。

  3. 您可以使用接口回调到活动/片段以触发来自Retrofit调用的更新。


6
我同意你的回答,但你并没有向提问者展示如何实现这些,所以我认为它并没有增加太多价值 :) 你应该考虑在每个条目中添加简单的示例。 - a_local_nobody

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接