处理Kotlin Coroutines中的自定义okhttp拦截器引发的异常

我在Android应用中使用了自定义Interceptor和Retrofit客户端,在某些特定情况下会引发Exception。我正在尝试使用Kotlin协程使其正常工作。

问题是我无法处理前面提到的错误,因为从Interceptor实例内部抛出异常的那一刻,它使整个应用程序崩溃,而不是被协程的try/catch语句捕获。当我使用Rx实现时,异常被完美地传播到了onError回调中,在那里我能够以所需的方式对其进行处理。

我想这与网络调用所使用的基础线程有某种关系,请在发出异常之前从进行调用的地方,拦截器以及堆栈跟踪中查看下面的日志:

2019-11-04 17:17:34.515 29549-29729/com.app W/TAG: Running thread: DefaultDispatcher-worker-1
2019-11-04 17:17:45.911 29549-29834/com.app W/TAG: Interceptor thread: OkHttp https://some.endpoint.com/...

2019-11-04 17:17:45.917 29549-29834/com.app E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: com.app,PID: 29549
    com.app.IllegalStateException: Passed refresh token can\'t be used for refreshing the token.
        at com.app.net.AuthInterceptor.intercept(AuthInterceptor.kt:33)

我应该怎么做才能正确地从拦截器捕获并处理此异常?我想念什么吗?

jacky0212 回答:处理Kotlin Coroutines中的自定义okhttp拦截器引发的异常

您应该继承IOException的子类,并使用该子类将信息从拦截器发送到调用代码。

我们认为诸如IllegalStateException之类的其他异常是应用程序崩溃,不要将它们发送到线程边界之外,因为我们不想让大多数调用者都无法捕获它们。

,

您可能会在自定义 Interceptor 中捕获异常并返回带有某些特定 messagecode 的空响应。我已经实现了一个自定义 Interceptor 来处理诸如没有互联网连接或互联网连接速度慢等情况......实际上协程的挂起函数在处理网络调用时会抛出异常。根据我的经验,您可以遵循两种方法。 1. 将您的所有网络调用包装在 try...catch2. 创建自定义 Interceptor 并在那里处理异常并返回一些特定响应。 >

方法 1:

try {
    webservice.login(username,password)
} catch (e: Exception) {
    //...
}

方法 2:

创建自定义 Interceptor 并在那里处理异常。

class LoggingInterceptor : Interceptor {

   @Throws(Exception::class)
   override fun intercept(chain: Interceptor.Chain): Response {
      val request = chain.request()
      try {
          val response = chain.proceed(request)
        
          val bodyString = response.body()!!.string()

          return response.newBuilder()
            .body(ResponseBody.create(response.body()?.contentType(),bodyString))
            .build()
      } catch (e: Exception) {
          e.printStackTrace()
          var msg = ""
          when (e) {
             is SocketTimeoutException -> {
                msg = "Timeout - Please check your internet connection"
             }
             is UnknownHostException -> {
                msg = "Unable to make a connection. Please check your internet"
             }
             is ConnectionShutdownException -> {
                msg = "Connection shutdown. Please check your internet"
             }
             is IOException -> {
                msg = "Server is unreachable,please try again later."
             }
             is IllegalStateException -> {
                msg = "${e.message}"
             }
             else -> {
                msg = "${e.message}"
             }
          }

          return Response.Builder()
                .request(request)
                .protocol(Protocol.HTTP_1_1)
                .code(999)
                .message(msg)
                .body(ResponseBody.create(null,"{${e}}")).build()
      }
   }
}

我已经为 LoggingInterceptor 的完整实现创建了要点,并带有请求和响应的打印日志。 LoggingInterceptor

,

我不知道您到底需要什么,但是这样理解:

    OkHttpClient okHttpClient = new OkHttpClient.Builder()  
        .addInterceptor(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                okhttp3.Response response = chain.proceed(request);

                // todo deal with the issues the way you need to
                if (response.code() == SomeCode) {
                   //do something
                    return response;
                }

                return response;
            }
        })
        .build();

Retrofit.Builder builder = new Retrofit.Builder()  
        .baseUrl(url)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create());

Retrofit retrofit = builder.build();  
本文链接:https://www.f2er.com/3165227.html

大家都在问