Reputation: 4712
I would like to change my current try catch block to the function side. With my current implementation, I always have to write try catch
and the calling side of my function, but I don't want this boilerplate code. This is my current implementation:
inline fun ActivityResult.checkResultAndExecute(block: ActivityResult.() -> Unit) {
if (resultCode == Activity.RESULT_OK) this.block()
else Timber.e("FrameworkUtils: Something went wrong on Registering a ActivityResult")
}
result.checkResultAndExecute {
try {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
val account = task.getResult(ApiException::class.java)
loginViewModel.onEvent(LoginRegistrationEvent.SignInWithGoogle(account))
} catch (e: Exception) {
toast("Error")
}
}
What I want is something like this (Current implementation):
inline fun ActivityResult.newCheckResultAndExecture(block: ActivityResult.(Exception?) -> Unit) {
// Call function on ActivityResult. If an exception happens, then push it back to callin side
try {
this.block(null)
} catch (e: Exception) {
this.block(e)
}
}
But I don't think that the way I wrote the new function is correct
Upvotes: 1
Views: 528
Reputation: 93659
This seems like an error-prone way to handle errors. It's surprising that the same lambda handles both the try block and the catch block, and it's also surprising that the lambda is run twice when there's an error. There's a lot of room for using the function incorrectly.
You might consider using the standard library runCatching
function to build something similar that is less error-prone:
inline fun <T> ActivityResult.runIfOkCatching(block: ActivityResult.() -> T): Result<T> =
if (resultCode == Activity.RESULT_OK) runCatching(block)
else Result.failure(Exception("FrameworkUtils: Something went wrong on Registering a ActivityResult"))
// At call site:
result.runIfOkCatching {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
val account = task.getResult(ApiException::class.java)
loginViewModel.onEvent(LoginRegistrationEvent.SignInWithGoogle(account))
}.onFailure { e ->
// Handle exception from running block or from resultCode not OK
}
Or if you don't want to treat a not-OK result as a failure, but simply log and do nothing:
inline fun ActivityResult.runIfOkCatching(block: ActivityResult.() -> Unit): Result<Unit> =
if (resultCode == Activity.RESULT_FIRST_USER) {
runCatching(block)
} else {
Timber.e("FrameworkUtils: Something went wrong on Registering a ActivityResult")
Result.success(Unit)
}
Upvotes: 1
Reputation: 2446
As I understand you just need to add error listener. If so you can use following code:
inline fun ActivityResult.checkResultAndExecture(block: ActivityResult.(Exception?) -> Unit, onErrorListener: ((Exception) -> Unit)? = null) {
try {
if (resultCode == Activity.RESULT_OK) this.block()
else Timber.e("FrameworkUtils: Something went wrong on Registering a ActivityResult")
} catch (e: Exception) {
onErrorListener?.invoke(e)//in case of null listener is a bad approach
}
}
I wrote simple solution with listener call, but it is not a best one, because with null listener you would miss exceptions. That can lead some unpleasant shadow error. Better at least to write them to log.
Upvotes: 1