Search code examples
androidapiretrofitretrofit2synchronous

Synchronous API call using retrofit execute


Im trying to do a synchronous api call in Kotlin android, actually I'm having a function with 2 parameters and I need to make a post request and get a particular response for it and depending on the response i have to return true or false.

I have tried enqueue() & execute() from Retrofit2 but execute() works on the UI thread. even tried making a thread and run still the return statement execute before the response.

        private fun check(v1: String, v2: String): Boolean {

            val vObj = ValidateObj( v1, v2 )
            val boolcheck = false
            Thread {
                try {
                    val retrofit = ServiceBuilder.buildService(API::class.java)
                    val res = retrofit.validate(vObj).execute() 
                    boolcheck = res.code() == 200
                } catch (e: Exception) {
                    boolcheck = false
                }
            }.start()
            return true
        }

I have seen most the the answers for the same nothing seems working for me as the code provided was not complete/ wrong.

Please help with a sample code if possible. (Thanks in advance.)


Solution

  • The problem with your sample code is that inside your function check(p1, p2) you start a new Thread. This means your Thread which started the function will continue and return true. You must add a way to wait for the execution of the call and then continue your process with the result.

    There are multiple ways to achieve this:

    1. with Callback
    private fun check(v1: String, v2: String, onResult: (Boolean) -> Unit) {
                val vObj = ValidateObj( v1, v2 )
                Thread {
                    val result = runCatching {
                        val retrofit = ServiceBuilder.buildService(API::class.java)
                        val res = retrofit.validate(vObj).execute() 
                        res.code() == 200
                    }.getOrDefault(false)
    
                    onResult(result) // result will then be on the other thread and you have to switch back if necessary
                }.start()
            }
    
    
    //with Coroutine
    private fun check(v1: String, v2: String, onResult: (Boolean) -> Unit) {
                val vObj = ValidateObj( v1, v2 )
                CoroutineScope(Dispatchers.IO).launch {
                    val result = runCatching {
                        val retrofit = ServiceBuilder.buildService(API::class.java)
                        val res = retrofit.validate(vObj).execute() 
                        res.code() == 200
                    }.getOrDefault(false)
    
                    onResult(result) // result will then be on the other thread and you have to switch back if necessary
    
                    // e.g. CoroutineScope(Dispatchers.Main).launch{onResult(result)}
                  
                }
            }
    
    
    fun logic(){
        check(p1, p2){ boolean ->
           // continue your logic
        }
    }
    
    1. with Coroutines
    private suspend fun check(v1: String, v2: String): Boolean = 
            withContext(Dispatchers.IO){
                val vObj = ValidateObj( v1, v2 )
                
                runCatching {
                        val retrofit = ServiceBuilder.buildService(API::class.java)
                        val res = retrofit.validate(vObj).execute() 
                        res.code() == 200
                    }.getOrDefault(false)
           }    
    
    fun logic{
        
        //use function inside a coroutine, e.g.
        CoroutineScope(Dispatchers.Main).launch{
            val checkResult = check(p1, p2)
    
            ...
        }
    
    }