如何使吞噬异常的功能

Pit*_*tel 2 kotlin

inline fun <T> rest(request: () -> T): T = try {
    request()
} catch (e: HttpException) {
    val requestId = e.response().raw().request().header(REQUEST_ID_HEADER) 
    if (requestId != null) {
        Dialog(requestId, R.string.oops).show(fragmentManager, null)
    } else {
        throw e
    }
}
Run Code Online (Sandbox Code Playgroud)

它应该执行一些REST请求(在request参数中),如果失败,并且包含指定的HTTP标头,则显示带有该标头的对话框。

但是编译器抱怨Dialog,它不返回T,而是Unit。但这基本上就是我想要的!我怎样才能做到这一点?

我想到的一个解决方案是将函数的返回类型设置为T?return null,但是在Kotlin中这样做很脏

Jof*_*rey 5

返回null 本身并不。使用null有时会被滥用,但这是使用null的完美有效的用例。Kotlin允许您以安全,美观的方式使用null,因此不要害怕使用它!

另一种选择是在显示对话框的情况下(无论是否存在标题)都引发异常。

为了进行选择,您必须问自己rest(),如果显示对话框,代码调用将执行什么操作。它必须T一种或另一种方式(空或异常)处理缺失。这是因为显示对话框并不能结束函数的执行。

最后但并非最不重要的一点是,还有一个方法可以处理rest()方法之外的结果。改善Taras的答案:

sealed class Result<out T : Any> {
    class Success<out T : Any>(val value: T) : Result<T>()
    class ErrorWithId(val exception: Exception, val requestId: String) : Result<Nothing>()
    class Error(val exception: Exception) : Result<Nothing>()
}

inline fun <T : Any> rest(request: () -> T): Result<T> = try {
    Result.Success(request())
} catch (e: HttpException) {
    val requestId = e.response().raw().request().header(REQUEST_ID_HEADER)
    if (requestId != null) {
        Result.RecoverableError(e, requestId)
    } else {
        Result.Error(e)
    }
}

private fun thingCallingRest() {
    val result = rest(::testRequest)
    when (result) {
        is Result.Success -> Log.v("__DEBUG", "success: ${result.value}")
        is Result.ErrorWithId -> Dialog(result.requestId, R.string.oops).show(fragmentManager, null)
        is Result.Error -> throw result.exception
    }
}
Run Code Online (Sandbox Code Playgroud)