Search code examples
kotlintimerkotlin-coroutines

Suspend `withTimeout`


My app starts from executing coroutine:

model.viewModelScope.launch(Dispatchers.IO) {
            val timeout = withTimeoutOrNull(TIMEOUT) {
            //send some initialization server requests
            true   //timeout=true
    }
    if (timeout!=null){
        // app started ok
    } else {
        // app freezed on start
    }
}

The problem is one of the initialization step - obtain user consent to share his personal data(GDPR) Consent form is a modal popup that waits for user input.But the timer is ticking all this time. Therefore after gdpr user may see app starts too long error.

Is there way to suspend withTimeoutOrNull timer and resume it after some time?


Solution

  • It is not supported out of the box, but you can write your own version of withTimeoutOrNull that would support a pauseable timer. The key idea is to run your block in a separate coroutineScope { ... } and to launch a secondary helper coroutine that would cancel this scope after timeout. Now if you keep a reference to this helper cancellationJob, then you can cancel it when you need to pause your time and restart it when you need to resume timer.

    That would give you essentially the same behavior that basic withTimeout has but with an added pauseability. A bit of extra code is needed to implement a withTimeoutOrNull variant. You'll need to catch your cancellation exception and replace it with null result.

    A worked-out implementation can be found in this gist: https://gist.github.com/elizarov/c5b0fde43ca14efbb8bcab13ad43c6ca