Home > front end >  How to return response body from function with retrofit and kotlin?
How to return response body from function with retrofit and kotlin?

Time:09-30

Here is my code:

fun getRandomComputerDetails(context: Context) {
    if (isNetworkAvailable(context)) {
        val retrofit: Retrofit = Retrofit.Builder()
            .baseUrl(BuildConfig.API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val service: RandomComputerApiService =
            retrofit.create(RandomComputerApiService::class.java)

        val listCall: Call<RandomComputerApiResponse> = service.getRandomComputer()

        listCall.enqueue(object : Callback<RandomComputerApiResponse> {
            override fun onResponse(
                call: Call<RandomComputerApiResponse>,
                response: Response<RandomComputerApiResponse>
            ) {
                if (response.isSuccessful) {
                    val randomComputerList: RandomComputerApiResponse? = response.body()
                    if (randomComputerList != null) {
                        // TODO how to return randomComputerList?
                    }
                    Log.i("Response result", "$randomComputerList")
                } else {
                    when (response.code()) {
                        400 -> {
                            errorDialogHandler(context, R.string.dialog_error_400)
                            Log.e("Error 400", "Bad Connection")
                        }
                        404 -> {
                            errorDialogHandler(context, R.string.dialog_error_404)
                            Log.e("Error 404", "Not Found")
                        }
                        500 -> {
                            errorDialogHandler(context, R.string.dialog_error_500)
                            Log.e("Error 500", "Server Error")
                        }
                        else -> {
                            errorDialogHandler(context, R.string.dialog_error_generic_error)
                            Log.e("Error", "Generic Error")
                        }
                    }
                }
            }

            override fun onFailure(call: Call<RandomComputerApiResponse>, t: Throwable) {
                Log.e("Response error", t.message.toString())
            }
        })
    } else {
        // NO INTERNET CONNECTION
        errorDialogHandler(context, R.string.dialog_error_no_internet_connection)
    }
}

How can i return my randomComputerList body in order to use it in a Fragment? I'm using retrofit2 and my idea it was to separate in a specific file the function that takes care of executing the logic for the API call, and then calling it later in a fragment.

CodePudding user response:

An alternative to callback interfaces is to use coroutines. To do that, mark this as a suspend function and use await() instead of enqueue(). The await() call must be wrapped in a try/catch to capture the failure condition (analogous to onFailure in enqueue()). And I moved the no-network condition to the start so you don't have to nest all your code in an if-block.

suspend fun getRandomComputerDetails(context: Context): RandomComputerApiResponse? {
    if (!isNetworkAvailable(context)) {
        // NO INTERNET CONNECTION
        errorDialogHandler(context, R.string.dialog_error_no_internet_connection)
        return null
    }
    val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BuildConfig.API_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val service: RandomComputerApiService =
        retrofit.create(RandomComputerApiService::class.java)

    val response = try { 
        service.getRandomComputer().await() 
    } catch (t: Throwable) {
        // code for failure condition
        // errorDialogHandler(context, R.string.???)
        Log.e("Response error", t.message.toString())
        return null
    }

    if (response.isSuccessful) {
        return response.body()
    }

    when (response.code()) {
        400 -> {
            errorDialogHandler(context, R.string.dialog_error_400)
            Log.e("Error 400", "Bad Connection")
        }
        404 -> {
            errorDialogHandler(context, R.string.dialog_error_404)
            Log.e("Error 404", "Not Found")
        }
        500 -> {
            errorDialogHandler(context, R.string.dialog_error_500)
            Log.e("Error 500", "Server Error")
        }
        else -> {
            errorDialogHandler(context, R.string.dialog_error_generic_error)
            Log.e("Error", "Generic Error")
        }
    }
    return null
}

And then in your fragment:

lifecycleScope.launch {
    val response = getRandomComputerDetails(requireContext())
    if (response != null) {
        // Do something with response of type RandomComputerApiResponse
    }
}

CodePudding user response:

You can create interface and return result through it for example I have created a ResultListener interface

interface ResultListener<S> {
    fun onSuccess(successModel: S)
    fun onFail(any: String?)
    fun onError(e: Throwable?)
}

and pass interface and take result from interface using resultListener.onSuccess(randomComputerList) on response.isSuccessful

fun getRandomComputerDetails(context: Context, resultListener: ResultListener<RandomComputerApiResponse>) {
    if (isNetworkAvailable(context)) {
        val retrofit: Retrofit = Retrofit.Builder()
            .baseUrl(BuildConfig.API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val service: RandomComputerApiService =
            retrofit.create(RandomComputerApiService::class.java)

        val listCall: Call<RandomComputerApiResponse> = service.getRandomComputer()

        listCall.enqueue(object : Callback<RandomComputerApiResponse> {
            override fun onResponse(
                call: Call<RandomComputerApiResponse>,
                response: Response<RandomComputerApiResponse>
            ) {
                if (response.isSuccessful) {
                    val randomComputerList: RandomComputerApiResponse? = response.body()
                    if (randomComputerList != null) {
                        // TODO how to return randomComputerList?
                        resultListener.onSuccess(randomComputerList)
                    }
                    Log.i("Response result", "$randomComputerList")
                } else {
                    when (response.code()) {
                        400 -> {
                            errorDialogHandler(context, R.string.dialog_error_400)
                            Log.e("Error 400", "Bad Connection")
                        }
                        404 -> {
                            errorDialogHandler(context, R.string.dialog_error_404)
                            Log.e("Error 404", "Not Found")
                        }
                        500 -> {
                            errorDialogHandler(context, R.string.dialog_error_500)
                            Log.e("Error 500", "Server Error")
                        }
                        else -> {
                            errorDialogHandler(context, R.string.dialog_error_generic_error)
                            Log.e("Error", "Generic Error")
                        }
                    }
                }
            }

            override fun onFailure(call: Call<RandomComputerApiResponse>, t: Throwable) {
                Log.e("Response error", t.message.toString())
            }
        })
    } else {
        // NO INTERNET CONNECTION
        errorDialogHandler(context, R.string.dialog_error_no_internet_connection)
    }
}

For calling this fun

getRandomComputerDetails(
    context = this,
    resultListener = object : ResultListener<RandomComputerApiResponse> {
        override fun onSuccess(successModel: RandomComputerApiResponse) {
            //handle success result
        }

        override fun onFail(any: String?) {
            //handle Fail result
        }

        override fun onError(e: Throwable?) {
            //handle Error
        }
    })
  • Related