Why is my coroutine ran repeatedly after function finishes?

Viewed 53

I'm currently in a network service, where im adding an interceptor and listening for a 401. If a 401 happens, i then want to sign the user out and navigate back to my LoginActivity. This all works as expected, except the coroutine keeps being ran even after navigating to LoginActivity, causing new activities to be created constantly. Is there a way i can cancel this coroutine once the navigation has happened?

  val httpClient = OkHttpClient.Builder().apply {

            addInterceptor {

                val token = runBlocking {
                    tokenStore.getToken().first()?.token
                }

                val response = it.proceed(
                    it.request().newBuilder()
                        .addHeader(HEADER_AUTH, "Bearer $token")
                        .addHeader(HEADER_ACCEPT, "application/json").build()
                )

                if (response.code == 401) {
                    GlobalScope.launch {
                        signout(
                            tokenStore,
                            manager,
                            context
                        )
                    }
                    context.startActivity(
                        Intent(context, LoginActivity::class.java).setFlags(
                            Intent.FLAG_ACTIVITY_NEW_TASK
                        )
                    )
                }
                response
            }
            addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
        }.build()
1 Answers

I see two issues with this code:

  1. You are launching multiple coroutines (runBlocking + launch)
  2. In case of multiple concurrent calls that fail, each one will start LoginActivity

For 1) you need to wrap the whole interceptor call in runBlocking, so you can write suspend functions freely

For 2) you can use a Mutex to make sure the interceptor runs once at a time

Related