Evg*_*urg 5 android kotlin kotlin-android-extensions kotlin-coroutines
我有一个简单的设置:
lifecycleScope.launch {
val result = test()
}
suspend fun test(): Result<Unit> = withContext(Dispatchers.IO) {
Result.failure(IllegalStateException("QWER"))
}
Run Code Online (Sandbox Code Playgroud)
实际结果: 上面的代码崩溃了:java.lang.IllegalStateException: QWER
预期结果: 结果对象按预期返回
我使用 kotlin 1.4.10 和协程 1.3.9。我使用 kotlin.Result 对象作为返回类型,为此我有:
kotlinOptions {
freeCompilerArgs = ["-Xallow-result-return-type"]
}
Run Code Online (Sandbox Code Playgroud)
另一件事是,如果我使用主上下文 (Dispatchers.Main) 执行协程,一切都会按预期进行。
UPDATE 从 Kotlin 1.5 开始,Result 被用作 Kotlin 函数的直接结果类型。更多详情请参阅 KEEP
我也有同样的崩溃。这些代码在 Kotlin 1.3.72 时可以工作,但在 1.4.0 时崩溃。我的解决方案是将其复制kotlin.Result到我的项目中。
class Result<out T>(val value: Any?) {
val isSuccess: Boolean get() = value !is Failure
val isFailure: Boolean get() = value is Failure
fun getOrNull(): T? = when {
isFailure -> null
else -> value as T
}
fun exceptionOrNull(): Throwable? = when (value) {
is Failure -> value.exception
else -> null
}
override fun toString(): String =
when (value) {
is Failure -> value.toString() // "Failure($exception)"
else -> "Success($value)"
}
companion object {
fun <T> success(value: T): Result<T> = Result(value)
fun <T> failure(exception: Throwable): Result<T> = Result(createFailure(exception))
}
class Failure(val exception: Throwable) {
override fun equals(other: Any?): Boolean = other is Failure && exception == other.exception
override fun hashCode(): Int = exception.hashCode()
override fun toString(): String = "Failure($exception)"
}
}
private fun createFailure(exception: Throwable): Any = Result.Failure(exception)
inline fun <R, T> Result<T>.fold(
onSuccess: (value: T) -> R,
onFailure: (exception: Throwable) -> R
): R {
return when (val exception = exceptionOrNull()) {
null -> onSuccess(value as T)
else -> onFailure(exception)
}
}
inline fun <R, T> Result<T>.map(transform: (value: T) -> R): Result<R> {
return when {
isSuccess -> Result.success(transform(value as T))
else -> Result(value)
}
}
inline fun <T> Result<T>.onFailure(action: (exception: Throwable) -> Unit): Result<T> {
exceptionOrNull()?.let { action(it) }
return this
}
inline fun <T> Result<T>.onSuccess(action: (value: T) -> Unit): Result<T> {
if (isSuccess) action(value as T)
return this
}
fun <T> Result<T>.getOrThrow(): T {
throwOnFailure()
return value as T
}
fun Result<*>.throwOnFailure() {
if (value is Result.Failure) throw value.exception
}
inline fun <R, T : R> Result<T>.getOrElse(onFailure: (exception: Throwable) -> R): R {
return when (val exception = exceptionOrNull()) {
null -> value as T
else -> onFailure(exception)
}
}
fun <R, T : R> Result<T>.getOrDefault(defaultValue: R): R {
if (isFailure) return defaultValue
return value as T
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
617 次 |
| 最近记录: |