Search code examples
androidkotlinretrofit2countdownlatch

CountDownLatch freezes thread on Android


I have a method, where I would like to check the validity of my token through an API call with Retrofit and I want to wait for the result. I thought to use CountDownLatch but it seems countDownLatch.await() locks the thread and nothing happens, the debugger doesn't get to the onResponse part. I checked my API with Postman, the call actually hits it.

I also found this question which is similar to my problem but it didn't help: CountDownLatch not freeing thread

    var isTokenExpired = false

    var countDownLatch = CountDownLatch(1)

    val userService = RetrofitClient.getInstance().create(DiaBUserService::class.java)
    userService.validate(token).enqueue(object : Callback<JsonObject> {
        override fun onResponse(call: Call<JsonObject>, response: Response<JsonObject>) {
            isTokenExpired = !response.isSuccessful
            countDownLatch.countDown()
        }

        override fun onFailure(call: Call<JsonObject>, t: Throwable) {
            t.printStackTrace()
            countDownLatch.countDown()
        }
    })

    try {
        countDownLatch.await()
    } catch (e: InterruptedException){
        e.printStackTrace()
    }

    return isTokenExpired

Do I use anything wrong or is there any other way the get the desired function?


Solution

  • The Retrofit Callback documentation says:

    Callbacks are executed on the application's main (UI) thread.
    

    The main thread is blocked on the method CountDownLatch#await, so CountDownLatch#countDown will not be executed. You can specify a background executor for the callbacks to run on (for example SingleThreadExecutor).

    val retrofit = Retrofit.Builder()
            // options
            .callbackExecutor(Executors.newSingleThreadExecutor())
            // options
            .build()