Returning a value after callback in Kotlin

前端 未结 2 1469
借酒劲吻你
借酒劲吻你 2021-01-29 05:40

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: Retro         


        
相关标签:
2条回答
  • 2021-01-29 05:50

    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. 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)
              }
          })
      }
      

    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
        }
    }
    

    And now call to searchColorFromApi should look like this

    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()
      

    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)
                }
            })
        }
    

    and in your activity do following

      fun setupObservers(){
           yourApiCallingClass.colors.observe(this, Observer {
            // this code is called when ever value of color field changes
           })
       }
    
    0 讨论(0)
  • 2021-01-29 06:02
    1. You can use live data ,that gets updated once the callback receives ,the same live data is observed by the caller fragment/activity

    2. You can use coroutines to return a value from function which has asyn calls in it.

    3. You can use interface callbacks to activity/ fragment to trigger the updates received from retrofit calls.

    0 讨论(0)
提交回复
热议问题