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...
}