suspendRunCatching
Executes a suspending operation and returns the result wrapped in Result, with proper coroutine cancellation handling.
This is the standard error handling utility used across all repository methods in the application. It's similar to Kotlin's runCatching but properly handles coroutine cancellation by re-throwing CancellationException instead of catching it.
Why Use This Instead of runCatching?
The standard runCatching catches ALL exceptions, including CancellationException, which breaks coroutine cancellation. This function preserves cancellation behavior while catching other exceptions.
Usage in Repository Layer
class UserRepositoryImpl @Inject constructor(
private val networkDataSource: NetworkDataSource,
private val localDataSource: LocalDataSource,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
) : UserRepository {
override suspend fun getUser(id: String): Result<User> = suspendRunCatching {
withContext(ioDispatcher) {
networkDataSource.getUser(id)
}
}
override suspend fun syncUsers(): Result<Unit> = suspendRunCatching {
withContext(ioDispatcher) {
val users = networkDataSource.getUsers()
localDataSource.saveUsers(users)
}
}
}Integration with State Management
This function is designed to work seamlessly with updateStateWith and updateWith:
@HiltViewModel
class UserViewModel @Inject constructor(
private val repository: UserRepository
) : ViewModel() {
fun loadUser(id: String) {
_uiState.updateStateWith {
repository.getUser(id) // Already wrapped in Result via suspendRunCatching
}
}
}Exception Handling
Success: Returns
Result.success(value)CancellationException: Re-thrown to preserve coroutine cancellation
Other exceptions: Returns
Result.failure(exception)
Best Practices
Use at the repository boundary (not in ViewModels or UI)
Combine with
withContext(ioDispatcher)for IO operationsLet exceptions propagate from data sources unchanged
Don't nest multiple
suspendRunCatchingcalls
Return
Result.success with the value if successful, Result.failure if an exception occurred.
Parameters
The type of the result value.
The suspending operation to execute.
See also
Throws
if the coroutine is cancelled (not caught).