简体   繁体   English

如何使用 retrofit2 动态设置超时?

[英]How to setup timeout dynamically with retrofit2?

public class Router {

    ...

    private static Retrofit retrofit = null;

    ...

    public Retrofit getRetrofit() {
        if (retrofit == null) {

            ...

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl("***")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }

    ...

}

I setup timeout in OkHttpClient .我在OkHttpClient中设置超时。 Now there is a API needs different timeout.现在有一个API需要不同的超时。

How can i do?我能怎么做?

Is there something like this?有这样的东西吗?

@Timeout
Observable<ResponseBody> exapmle(@Timeout("connect") int connect
 , @Timeout("read") int read
 , @Timeout("write") int write);

在此处输入图片说明

Thanks a lot.非常感谢。

here is my code:这是我的代码:

public static final String CONNECT_TIMEOUT = "CONNECT_TIMEOUT";
public static final String READ_TIMEOUT = "READ_TIMEOUT";
public static final String WRITE_TIMEOUT = "WRITE_TIMEOUT";

...

Interceptor timeoutInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        int connectTimeout = chain.connectTimeoutMillis();
        int readTimeout = chain.readTimeoutMillis();
        int writeTimeout = chain.writeTimeoutMillis();

        String connectNew = request.header(CONNECT_TIMEOUT);
        String readNew = request.header(READ_TIMEOUT);
        String writeNew = request.header(WRITE_TIMEOUT);

        if (!TextUtils.isEmpty(connectNew)) {
            connectTimeout = Integer.valueOf(connectNew);
        }
        if (!TextUtils.isEmpty(readNew)) {
            readTimeout = Integer.valueOf(readNew);
        }
        if (!TextUtils.isEmpty(writeNew)) {
            writeTimeout = Integer.valueOf(writeNew);
        }

        return chain
                .withConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
                .withReadTimeout(readTimeout, TimeUnit.MILLISECONDS)
                .withWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS)
                .proceed(request);
    }
};

OkHttpClient httpClient = new OkHttpClient.Builder()
        .connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
        .writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
        .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
        .addInterceptor(timeoutInterceptor)
        .build();

retrofit = new Retrofit.Builder()
        .baseUrl(Host.Develop.ACCOUNT_HOST)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .client(httpClient)
        .build();

...

example usage:用法示例:

/**
 * check account status
 *
 * @param account
 * @return
 */
@Headers({"CONNECT_TIMEOUT:10000", "READ_TIMEOUT:10000", "WRITE_TIMEOUT:10000"})
@GET("login/prelogin")
Observable<ResponseBody> preLogin(@Query("account") String account);

or要么

/**
 * check account status
 * 
 * @param connectTimeout
 * @param readTimeout
 * @param writeTimeout
 * @param account
 * @return
 */
@GET("login/prelogin")
Observable<ResponseBody> preLogin(
        @Header("CONNECT_TIMEOUT") String connectTimeout,
        @Header("READ_TIMEOUT") String readTimeout,
        @Header("WRITE_TIMEOUT") String writeTimeout,
        @Query("account") String account);

Kotlin科特林

Interceptor拦截器

class TimeHeaderInterceptor : Interceptor {

    companion object {
        private const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
        private const val READ_TIMEOUT = "READ_TIMEOUT"
        private const val WRITE_TIMEOUT = "WRITE_TIMEOUT"
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        var connectTimeout = chain.connectTimeoutMillis()
        var readTimeout = chain.readTimeoutMillis()
        var writeTimeout = chain.writeTimeoutMillis()

        val builder = request.newBuilder()

        request.header(CONNECT_TIMEOUT)?.also {
            connectTimeout = it.toInt()
            builder.removeHeader(CONNECT_TIMEOUT)
        }

        request.header(READ_TIMEOUT)?.also {
            readTimeout = it.toInt()
            builder.removeHeader(READ_TIMEOUT)
        }

        request.header(WRITE_TIMEOUT)?.also {
            writeTimeout = it.toInt()
            builder.removeHeader(WRITE_TIMEOUT)
        }

        return chain.run {
            withConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
            withReadTimeout(readTimeout, TimeUnit.MILLISECONDS)
            withWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS)
            proceed(builder.build())
        }
    }
}

OkHttpClient OkHttp客户端

OkHttpClient.Builder()
            .connectTimeout(15_000, TimeUnit.MILLISECONDS)
            .writeTimeout(15_000, TimeUnit.MILLISECONDS)
            .readTimeout(15_000, TimeUnit.MILLISECONDS)
            .addInterceptor(TimeHeaderInterceptor()) // config
            .build()

HttpApiImpl HttpApiImpl

interface HttpApiImpl {

    /**
     * Dynamic configuration time, example
     *
     */
    @Headers("CONNECT_TIMEOUT:1000", "READ_TIMEOUT:5000", "WRITE_TIMEOUT:2000")
    @GET
    fun time(@Url url: String): Observable<String>
}

Create a new retrofit instance where you pass in timeout values as parameters.创建一个新的改造实例,您可以在其中将超时值作为参数传递。

public Retrofit getRetrofit(int connectionTimeout, int readWriteTimeout) {
        if (retrofit == null) {

            ...

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(connectionTimeout, TimeUnit.SECONDS)
                    .writeTimeout(readWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(readWriteTimeout, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl("***")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }

There is no option like the below:没有像下面这样的选项:

@Timeout
Observable<ResponseBody> exapmle(@Timeout("connect") int connect
                , @Timeout("read") int read
                , @Timeout("write") int write);

this is my Kotlin Version:这是我的 Kotlin 版本:

Interceptor拦截器

const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
const val READ_TIMEOUT = "READ_TIMEOUT"
const val WRITE_TIMEOUT = "WRITE_TIMEOUT"

class TimeoutInterceptor : Interceptor {

    override fun intercept(chain: Chain): Response {
        val request: Request = chain.request()

        val connectTimeout =
            request.header(CONNECT_TIMEOUT)?.toInt() ?: chain.connectTimeoutMillis()
        val readTimeout = request.header(READ_TIMEOUT)?.toInt() ?: chain.readTimeoutMillis()
        val writeTimeout = request.header(WRITE_TIMEOUT)?.toInt() ?: chain.writeTimeoutMillis()

        return chain
            .withConnectTimeout(connectTimeout, MILLISECONDS)
            .withReadTimeout(readTimeout, MILLISECONDS)
            .withWriteTimeout(writeTimeout, MILLISECONDS)
            .proceed(request)
    }
}

OkHttpClient OkHttpClient

OkHttpClient.Builder()
            .connectTimeout(15_000, TimeUnit.MILLISECONDS)
            .writeTimeout(15_000, TimeUnit.MILLISECONDS)
            .readTimeout(15_000, TimeUnit.MILLISECONDS)
            .addInterceptor(TimeoutInterceptor()) // config
            .build()

Api Api

interface Api {

    @Headers("$CONNECT_TIMEOUT:300000", "$READ_TIMEOUT:300000", "$WRITE_TIMEOUT:300000")
    @GET
    fun time(@Url url: String): Observable<String>
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM