【发布时间】:2020-01-23 18:51:41
【问题描述】:
我遇到了这个异常: java.net.ProtocolException:W/System.err 流意外结束:在 okhttp3.internal.http1.Http1ExchangeCodec$FixedLengthSource.read(Http1ExchangeCodec.kt:392)
我正在尝试执行 SOAP 请求。我并不总是得到这个例外。有时我会从网络服务器得到正确的答案。
我将解析器库从 SimpleXML 更改为 TikXML,但我仍然遇到同样的问题。在 onResponse 方法中,我什么也没做,但我遇到了同样的问题。
这是我拨打电话的方式:
final Call<ResponseEnvelope> consumeWS = RetrofitGenerator
.getConsultarTipoDeDocumentoApi()
.getTiposDeDocumento(this.USERNAME_ENCRYPT, this.USERTOKEN_ENCRYPT,
this.MESSAGEID_ENCRYPT, "close", this.requestEnvelope);
consumeWS.enqueue(new Callback<ResponseEnvelope>() {
@Override
public void onResponse(Call<ResponseEnvelope> call, Response<ResponseEnvelope> response) {
ResponseEnvelope responseEnvelope = new ResponseEnvelope(response.body().getBody());
if(responseEnvelope != null && response.isSuccessful())
dataTipoDeDocumento.setValue(responseEnvelope.getBody().getMtrtipdoccResponse()
.getReturn().getLISTAREGISTROS().getLIST());
}
@Override
public void onFailure(Call<ResponseEnvelope> call, Throwable t) {
t.printStackTrace();
dataTipoDeDocumento.setValue(null);
这是我的 RetrofitGenerator:
private static OkHttpClient.Builder okHttpClient = new OkHttpClient
.Builder();
private static Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.create(serializer));
public RetrofitGenerator() {
}
public static <S> S createService(Class<S> serviceClass, String baseUrl) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = okHttpClient
.connectTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.addInterceptor(logging)
.build();
Retrofit retrofit = retrofitBuilder.baseUrl(baseUrl).client(client).build();
return retrofit.create(serviceClass);
}
问题出在这里:(调试请求)
override fun read(sink: Buffer, byteCount: Long): Long {
require(byteCount >= 0L) { "byteCount < 0: $byteCount" }
check(!closed) { "closed" }
if (bytesRemaining == 0L) return -1
val read = super.read(sink, minOf(bytesRemaining, byteCount))
if (read == -1L) {
realConnection!!.noNewExchanges() // The server didn't supply the promised content length.
val e = ProtocolException("unexpected end of stream")
responseBodyComplete()
throw e
}
我注意到当它失败时,有一个名为 bytesRemaining 的变量的值是 1(失败时它总是 1)。响应的内容长度始终为 933。我不知道发生了什么。
这是我的毕业作品:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.app.multired"
minSdkVersion 22
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
dataBinding {
enabled = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.jakewharton:butterknife:10.0.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
/* dagger dependency for DI*/
implementation "com.google.dagger:dagger:2.16"
annotationProcessor "com.google.dagger:dagger-compiler:2.16"
compileOnly 'javax.annotation:jsr250-api:1.0'
implementation 'javax.inject:javax.inject:1'
/*Retrofit lib*/
testImplementation 'com.squareup.okhttp3:mockwebserver:4.2.0'
implementation 'com.squareup.okhttp3:okhttp:4.2.0'
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.0'
//implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.squareup.retrofit2:converter-simplexml:2.6.1'
/*RxJava lib*/
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation "io.reactivex.rxjava2:rxjava:2.1.8"
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
/* LiveData lib*/
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "android.arch.lifecycle:runtime:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
implementation 'androidx.recyclerview:recyclerview:1.0.0'
/* Biometric Authentication */
implementation 'androidx.biometric:biometric:1.0.0-alpha03'
implementation 'org.jetbrains:annotations:15.0'
}
我是如何解决的:
public abstract class CallbackWithRetry<T> implements Callback<T> {
private static final String TAG = CallbackWithRetry.class.getSimpleName();
@Override
public void onFailure(Call<T> call, Throwable t){
Log.e(TAG, t.getLocalizedMessage());
retry(call);
}
private void retry(Call<T> call){
call.clone().enqueue(this);
}
}
编辑后的回调:
final Call<ConsultarTipoDeDocumentoResponseEnvelope> consumeWS = RetrofitGenerator
.getConsultarTipoDeDocumentoApi()
.getTiposDeDocumento(this.USERNAME_ENCRYPT, this.USERTOKEN_ENCRYPT,
this.MESSAGEID_ENCRYPT, this.consultarTipoDeDocumentoRequestEnvelope);
consumeWS.enqueue(new CallbackWithRetry<ConsultarTipoDeDocumentoResponseEnvelope>() {
@Override
public void onResponse(Call<ConsultarTipoDeDocumentoResponseEnvelope> call, Response<ConsultarTipoDeDocumentoResponseEnvelope> response) {
ConsultarTipoDeDocumentoResponseEnvelope consultarTipoDeDocumentoResponseEnvelope = new ConsultarTipoDeDocumentoResponseEnvelope(response.body().getBody());
if(consultarTipoDeDocumentoResponseEnvelope != null && response.isSuccessful())
dataTipoDeDocumento.setValue(consultarTipoDeDocumentoResponseEnvelope.getBody().getMtrtipdoccResponse()
.getReturn().getLISTAREGISTROS().getLIST());
}
@Override
public void onFailure(Call<ConsultarTipoDeDocumentoResponseEnvelope> call, Throwable t) {
super.onFailure(call, t);
}
});
此重试非常有用,因为 Retrofit2 在您进行入队调用时将调用变量作为 onFailure 方法的参数。
【问题讨论】:
标签: okhttp