Is it OK to use redundant/nested withContext calls?

Viewed 321

I have a personal project written in Kotlin, and I developed a habit of using withContext(...) very generously. I tend to use withContext(Dispatchers.IO) when calling anything that could possibly be related to I/O.

For example:

suspend fun getSomethingFromDatabase(db: AppDatabase) = withContext(Dispatchers.IO) {
    return // ...
}

suspend fun doSomethingWithDatabaseItem(db: AppDatabase) {
    val item = withContext(Dispatchers.IO) {
        getSomethingFromDatabase(db)
    }
    // ...
}

You can see a redundant withContext(Dispatchers.IO) in the second function. I'm being extra cautious here, because I might not know/remember if getSomethingFromDatabase switches to an appropriate context or not. Does this impact performance? Is this bad? What's the idiomatic way of dealing with Dispatchers?

Note: I know that it's perfectly fine to switch between different contexts this way, but this question is specifically about using the same context.

1 Answers

You do not need withContext for anything besides calling code that demands a specific context. Therefore withContext(Dispatchers.Main) should only be used when you're working with UI functions that require the main thread. And you should only use withContext(Dispatchers.IO) when calling blocking IO related code.

A proper suspend function does not block (see Suspending convention section here), and therefore, you should never have to specify a dispatcher to call a suspend function. The exception would be if you're working with someone else's code or API and they are using suspend functions incorrectly!

I don't know what your AppDatabase class is, but if it is sensibly designed, it will expose suspend functions instead of blocking functions, so you should not need withContext to retrieve values from it. But if it does expose blocking functions for retrieving items, then the code of your first function is correct.

And your second function definitely doesn't need withContext because it's simply using it to call something that I can see is a suspend function.

As for whether it's OK to use redundant context switching...it doesn't hurt anything besides possibly wasting a tiny bit of time and memory context switching and allocating lambdas for no reason. And it makes your code less readable.

Related