android - 改造 : java. lang.IllegalStateException: 关闭

标签 android retrofit2

我使用两种拦截器,一种是 HttpLoggingInterceptor 还有一个是我的自定义授权拦截器

我正在使用以下更新的改造版本库,

def retrofit_version = "2.7.2"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'
implementation 'com.squareup.okhttp3:okhttp:4.4.0'

下面是代码
private fun makeOkHttpClient(): OkHttpClient {
        val logger = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        return OkHttpClient.Builder()
            .addInterceptor(AuthorizationInterceptor(context)) <---- To put Authorization Barrier
            .addInterceptor(logger) <---- To log Http request and response
            .followRedirects(false)
            .connectTimeout(50, TimeUnit.SECONDS)
            .readTimeout(50, TimeUnit.SECONDS)
            .writeTimeout(50, TimeUnit.SECONDS)
            .build()
    }

当我尝试在名为 SynchronizationManager.kt 的文件中执行以下代码时,它给了我一个错误。
var rulesResourcesServices = RetrofitInstance(context).buildService(RulesResourcesServices::class.java)
val response = rulesResourcesServices.getConfigFile(file).execute() <---In this line I am getting an exception... (which is at SynchronizationManager.kt:185)               

我的 RulesResourcesServices 类(class)在这里

调试后我发现当调用下面的函数时,当时我得到了一个异常
@GET("users/me/configfile")
    fun getConfigFile(@Query("type") type: String): Call<ResponseBody>

我收到以下错误
java.lang.IllegalStateException: closed
at okio.RealBufferedSource.read(RealBufferedSource.kt:184)
at okio.ForwardingSource.read(ForwardingSource.kt:29)
at retrofit2.OkHttpCall$ExceptionCatchingResponseBody$1.read(OkHttpCall.java:288)
at okio.RealBufferedSource.readAll(RealBufferedSource.kt:293)
at retrofit2.Utils.buffer(Utils.java:316)<------- ANDROID IS HIGH-LIGHTING
at retrofit2.BuiltInConverters$BufferingResponseBodyConverter.convert(BuiltInConverters.java:103)
at retrofit2.BuiltInConverters$BufferingResponseBodyConverter.convert(BuiltInConverters.java:96)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.execute(DefaultCallAdapterFactory.java:97)
at android.onetap.SynchronizationManager.downloadFile(SynchronizationManager.kt:185)
at android.base.repository.LoginRepository.downloadConfigFilesAndLocalLogin(LoginRepository.kt:349)
at android.base.repository.LoginRepository.access$downloadConfigFilesAndLocalLogin(LoginRepository.kt:48)
at android.base.repository.LoginRepository$loginTask$2.onSRPLoginComplete(LoginRepository.kt:210)
at android.base.repository.LoginRepository$performSyncLogin$srpLogin$1$1.onSRPLogin(LoginRepository.kt:478)
at android.srp.SRPManager$SRPLoginOperation$execute$1.invokeSuspend(SRPManager.kt:323)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655)

下面是屏幕截图,您可以看到,我正在获取文件的输出,但不知道为什么它会引发异常。

enter image description here

检查 Retrofit 的 Utils 类

https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Utils.java
static ResponseBody buffer(final ResponseBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.source().readAll(buffer); <-This line throws an error.
    return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
  }

更新

使用 enqueue 方法也可以正常工作。
response.enqueue(object : Callback<ResponseBody?> {

override fun onResponse(call: Call<ResponseBody?>, response: retrofit2.Response<ResponseBody?>) { 
 }
})

我与改造团队发布了同样的问题,让我们看看。

https://github.com/square/retrofit/issues/3336

最佳答案

感谢 JakeWharton ( https://github.com/square/retrofit/issues/3336 ),我能够得到解决方案。
实际上在我的自定义拦截器中,我正在通过以下代码读取响应

Response.body().string()
我这样做是因为上面的代码帮助我找出是否有任何错误,而不是它是什么类型的错误......
如果是 AUTH_ERROR,我必须生成新 token 并将其附加到请求 header 。
根据retrofit document ,如果我们调用以下任何方法,则响应将被关闭,这意味着它不能被普通的 Retrofit 内部使用。
Response.close()
Response.body().close()
Response.body().source().close()
Response.body().charStream().close()
Response.body().byteStream().close()
Response.body().bytes()
Response.body().string()
所以要读取数据,我将使用
 response.peekBody(2048).string()
代替
 response.body().string(), 
所以它不会关闭响应。
下面是最终代码
 val response = chain.proceed(request)
            val body = response.peekBody(2048).string()//<---- Change
            try {
                if (response.isSuccessful) {
                    if (body.contains("status")) {
                        val jsonObject = JSONObject(body)
                        val status = jsonObject.optInt("status")
                        Timber.d("Status = $status")
                        if (status != null && status == 0) {
                            val errorCode = jsonObject.getJSONObject("data").optString("error_code")
                            if (errorCode != null) {
                                addRefreshTokenToRequest(request)
                                return chain.proceed(request)
                            }
                        }
                    } else {
                        Timber.d("Body is not containing status, might be not valid GSON")
                    }
                }
                Timber.d("End")
                
            } catch (e: Exception) {
                e.printStackTrace()
                Timber.d("Error")
            }
            return response

关于android - 改造 : java. lang.IllegalStateException: 关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60671465/

相关文章:

android - 试图在代码中获取属性值返回不正确的值

android - 使用 Rxjava 2 和 Retrofit 2 加载数据失败时应用程序崩溃

kotlin - PublishSubject 与 Kotlin 协程(流/ channel )

android - 改造 : Loading xml feed from url returns scrambled response body

安卓分页 : Using APIs with Retrofit and Gson (Crash)

java - 将 retrofit 回调值转换为返回封装对象

java - 使用android XmlPullParser解析XML文件的性能问题

android - 每次其他 LiveData 之一更新其值时,都会更新 LiveData 的值

java - 当调用新屏幕时,旧屏幕会被处理吗?

Android:strings.xml 中的 html