从挂起函数异常返回对象



Android project:

片段:

import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.Response
class DefaultTransportService {
    companion object {
        private val SERVICE_UNAVAILABLE = "{n" +
                "  "code": -1,n" + // 503
                "  "message": "Service unavailable"n" +
                "}"
        private val TAG = DefaultTransportService::class.java.name
        suspend fun executeOperation(operation: Deferred<Response<*>>): Any = withContext(Dispatchers.IO) {
            try {
                operation.await()
            } catch (e: Throwable) {
                val resultResponse = Response.error<Any>(-1, ResponseBody.create(
                        MediaType.parse("application/json"),
                        SERVICE_UNAVAILABLE
                ))
                return resultResponse
            }
        }
    }
}

排队

return resultResponse

我收到编译错误:

'return' is not allowed here

但是当operation.await()抛出任何异常时,我需要更改响应。

我直言,在您的情况下,我会让您的挂起函数返回一个sealed class,如下所示:

suspend fun doSomething(): Response =
        suspendCancellableCoroutine { cont ->
            try {
                // make some work here
                cont.resume(Response.Success())
            } catch (e: Exception) {
                val error = "Service unavailable"
                cont.resume(Response.Error(error))
                Log.e(TAG, e.message)
            }
        }
sealed class Response {
    class Success : Response()
    class Error(val message: String?) : Response()
}

1 - 创建密封类。返回一个密封的类,就像我已经提到过的那样,但它接受 T键入以返回结果。

sealed class Result<out T> {
    data class Success<out T>(val result: T): Result<T>()
    data class Failure<out T>(val exception: Exception) : Result<T>()
}

2- 用途

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main) 
    val result = fetch()
    
    when (result) {
        
        is Result.Success -> {
          val obj = result.result
        }
        is Result.Failure -> {
           Log.e(TAG, result.exception)
        }
    }
}

fun fetch(): Result<Object> {
    
    try { 
        return Result.Success(obj)
    } catch(e: Exception) {
        return Result.Failure(e)
    }
}
密封

类更明确,但从技术上讲,您不需要密封类,因为您可以使用resumeWithException来传播异常。

例:

suspend fun update() : Any = suspendCancellableCoroutine{ cont ->
    launch {
        try {
            // Some suspend functions that could throw exceptions
            val response = getData()
            parseData(response)
            cont.resume(Unit)
        }catch (e : Exception){
            cont.resumeWithException(e)
        }
    }
}

用法

try {
    network.update()
}catch (e: Exception) {
    // Handle your exceptions as usual
    when (e){
        is ParseException -> emit(Status.PARSING_ERROR)
        is NetworkException -> emit(Status.NETWORK_UNAVAILABLE
        // etc...
}

最新更新