Okhttp总是重试连接失败

时间:2017-07-07 20:44:57

标签: android retrofit2 okhttp3

如果我创建请求并且该请求返回4xx错误,则Retrofit / Okhttp会一直重试该请求。我将retryOnConnectionFailure设置为false并将超时设置为15秒,但似乎都被忽略了。我错过了什么吗?

private static OkHttpClient getClient() {
        return new OkHttpClient.Builder()
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
                .readTimeout(15, TimeUnit.SECONDS)
                .connectTimeout(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(false)
                .addInterceptor(chain -> {
                    Request request = chain.request()
                            .newBuilder()
                            .build();

                    return chain.proceed(request);
                }).build();
    }

    public static Retrofit getRetrofitClient(Gson gson){
        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(OkHttpLogger.getClient());
        if(gson != null){
            builder.addConverterFactory(GsonConverterFactory.create(gson));
        }else{
            builder.addConverterFactory(GsonConverterFactory.create());
        }

        return builder.build();
    }

我正在使用改装2.3.0和okhttp版本3.8.1

修改

我确实看到的一件事是,如果我设置5秒的超时,它可以完美地保持重试5秒然后给我一个失败但是如果我把它提高到10秒它就会继续前进并最终停止在2分钟左右

3 个答案:

答案 0 :(得分:2)

此代码可以帮助您,我在Application Class中使用Retrofit并在Manifest文件中将该类用作应用程序名称标记

public final class Application extends MultiDexApplication {

public static Retrofit retrofit;
public static String base_URL = "http://mds.devsiteurl.com/";

public static final String TAG = Application.class.getSimpleName();

private static Application mInstance;

public static synchronized Application getInstance() {
    return mInstance;
}
@Override
public void onCreate() {
    super.onCreate();

    mInstance = this;
    MultiDex.install(this);

    Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .readTimeout(15, TimeUnit.SECONDS) 
            .connectTimeout(15, TimeUnit.SECONDS)
            .build();

    retrofit = new Retrofit.Builder()
            .baseUrl(base_URL)
            .client(okHttpClient)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();
}
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}
}

在清单文件中

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mds.foundation.mdsfoundation">

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:name=".Application"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_apis_keys" />

    <activity android:name=".activity.MainActivity" />
    <activity
        android:name=".activity.CenterOfExcellenceActivity"
        android:windowSoftInputMode="adjustPan" />
    <activity android:name=".activity.SplashScreenActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

</manifest>

最后是gradle.build

apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
    applicationId "com.mds.foundation.mdsfoundation"
    minSdkVersion 19
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    multiDexEnabled true  //this line is important
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
packagingOptions {

    exclude 'META-INF/DEPENDENCIES.txt'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/notice.txt'
    exclude 'META-INF/license.txt'
    exclude 'META-INF/dependencies.txt'
    exclude 'META-INF/LGPL2.1'
}
useLibrary 'org.apache.http.legacy'
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
compile('org.apache.httpcomponents:httpmime:4.3.6') {
    exclude module: 'httpclient'
}
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'

//refrofit 
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.android.support:multidex:1.0.1'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.picasso:picasso:2.5.2'
testCompile 'junit:junit:4.12'
}

答案 1 :(得分:1)

问题是retryOnConnectionFailure不适用于408回复,因此它仍会自动重试

答案 2 :(得分:0)

您可以尝试创建自己的retryOnConnectionFailure拦截器:

这是kotlin中的代码:

open class MaxRetryCountInterceptor(private val retryLimit: Int) : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        var response = chain.proceed(request)
        var tryCount = 0

        while (!response.isSuccessful && tryCount < retryLimit) {
            tryCount++
            response = chain.proceed(request)
        }

        return response
    }
}

response.isSuccessful仅在代码介于200..300之间时成功