发布于2022年11月4日3年前 上篇文章讲解了怎么使用Kotlin的协程配合Retrofit发起网络请求,使用也是非常方便,但是在处理请求异常还不是很人性化。这篇文章,我们将处理异常的代码进行封装,以便对异常情况返回给页面,提供更加友好的提示。 编写拓展方法 我们写一个扩展(全局)方法,就叫ViewModelExt.kt,在下面创建方法。 /** * ViewModel扩展方法:启动协程 * @param block 协程逻辑 * @param onError 错误回调方法 * @param onComplete 完成回调方法 */ fun ViewModel.launch( block: suspend CoroutineScope.() -> Unit, onError: (e: Throwable) -> Unit = { _: Throwable -> }, onComplete: () -> Unit = {} ) { viewModelScope.launch( CoroutineExceptionHandler { _, throwable -> run { // 这里统一处理错误 ExceptionUtil.catchException(throwable) onError(throwable) } } ) { try { block.invoke(this) } finally { onComplete() } } } 统一异常处理 拓展方法里面对写成过程做了统一拦截,在onComplete方法可以做统一的异常处理 /** * 异常工具类 * @author ssq */ object ExceptionUtil { /** * 处理异常,toast提示错误信息 */ fun catchException(e: Throwable) { e.printStackTrace() when (e) { is HttpException -> { catchHttpException(e.code()) } is SocketTimeoutException -> { showToast(R.string.common_error_net_time_out) } is UnknownHostException, is NetworkErrorException -> { showToast(R.string.common_error_net) } is MalformedJsonException, is JsonSyntaxException -> { showToast(R.string.common_error_server_json) } is InterruptedIOException -> { showToast("服务器连接失败,请稍后重试") } // 自定义接口异常 is ApiException -> { showToast(e.message?:"", e.code) } is ConnectException -> { showToast( "连接服务器失败" ) } else -> { showToast("${MyApplication.instance.getString( R.string.common_error_do_something_fail )}:${e::class.java.name}") } } } /** * 处理网络异常 */ fun catchHttpException(errorCode: Int) { if (errorCode in 200 until 300) return// 成功code则不处理 showToast( catchHttpExceptionCode( errorCode ), errorCode ) } /** * toast提示 */ private fun showToast(@StringRes errorMsg: Int, errorCode: Int = -1) { showToast( MyApplication.instance.getString( errorMsg ), errorCode ) } /** * toast提示 */ private fun showToast(errorMsg: String, errorCode: Int = -1) { if (errorCode == -1) { ToastUtils.showShort(errorMsg) } else { ToastUtils.showShort("$errorCode:$errorMsg") } } /** * 处理网络异常 */ private fun catchHttpExceptionCode(errorCode: Int): Int = when (errorCode) { in 500..600 -> R.string.common_error_server in 400 until 500 -> R.string.common_error_request else -> R.string.common_error_request } } ApiException是自定义的异常类 如何使用 我们在一个ViewModel中可以这样使用 fun login(user: User) = launch({ val resultData = RetrofitClient.userService.login(user) if (resultData.code == 20000) { userInfo.value = RetrofitClient.userService.getUserInfo().data } },onError = { e: Throwable -> }) 如果是返回的结果不对,可以这样做 fun login(user: User) = launch({ val resultData = RetrofitClient.userService.login(user) if (resultData.code == 20000) { userInfo.value = RetrofitClient.userService.getUserInfo().data } else { throw ApiException(-1, "返回结果出错") } },onError = { e: Throwable -> }) ApiException是自定义的异常处理 使用Demo: 上篇文章:使用Kotlin协程配合Retrofit发送请求 本文来自博客园,作者:sw-code,转载请注明原文链接:https://www.cnblogs.com/sw-code/p/15591713.html
创建帐户或登录后发表意见