Retrofit 2.5.0 Invocation最佳动态配置请求timeout处理

Retrofit最佳动态配置请求timeout办法–Invocation

最近重构项目需要调整,
需要区分普通上传和辅助功能校验的超时.
为了提高用户体验,需要动态去进行配置.

传统方式

1.OkHttpClient设置

最传统的设置 请求超时时间的方法无疑是

 OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(connTimeout, TimeUnit.SECONDS)
                .readTimeout(connTimeout, TimeUnit.SECONDS)
                .writeTimeout(connTimeout, TimeUnit.SECONDS));

在创建OkhttpClient的时候,传入指定的timeout,
还可以在这里加上各种自定义拦截器(比如日志输出,user_agent,加签)
这个当然可以.
但是如果是一个大型项目,一个host的service内有着大量的请求接口.
在请求的时候,无疑是需要对OkHttpClient进行单例复用的,
这个时候需要对这种同一个host的其中的几个请求接口的超时时间进行独立控制,就不好处理了.

当然还有一种办法,

2.自定义拦截器请求地址比对

在创建OkHttpClient的时候,新增一个自定义拦截器,继承Interceptor,然后维护一个需要独立处理请求超时的地址集合.

@Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        String questUrl = request.url().toString();
     	//在这里进行请求地址判断.
        if ( isContains(questUrl)){
            Response proceed = chain.withConnectTimeout(timeout, TimeUnit.SECONDS)
                    .withReadTimeout(timeout, TimeUnit.SECONDS)
                    .withWriteTimeout(timeout, TimeUnit.SECONDS)
                    .proceed(request);
            return proceed;
        }
        return chain.proceed(request);
    }

通过维护一个地址集合,然后判断地址,再设置对应的超时时间.
这种方法也可以,
但是如果某些地址需要超时1秒,某些需要超时2秒,某些需要超时6秒,
那么可以预期得到,这样写起来会很蛋疼,
那么有没有什么更好的办法?
当然是有的!


最佳&最优雅的方式–Invocation

3.自定义拦截器与Invocation

经过上面的铺垫,
前面的2种方法,多多少少都有着一点缺陷和遗憾.
那么现在隆重介绍第3种方法,也是我个人认为最佳也是最优雅的办法.
首先请将Retrofit升级至 2.5.0
首先请将Retrofit升级至 2.5.0
首先请将Retrofit升级至 2.5.0
重要的事情说3遍.

  • 自定义注解.

先创建一个自定义注解,

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DynamicTimeout {
    int timeout();
}

注解名称可以按照自己的习惯起,代码内容也通俗易懂,当然也可以再加一个参数,比如说 Unit,也就是时间单位,指定设置超时时间是 毫秒或者 秒,这看具体的个人需求.

  • 添加注解

添加注解
使用起来也很简单,直接在指定方法上面添加注解,设置指定的超时时间即可,
简单易用!

  • 创建自定义拦截器

还是创建一个拦截器

 @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
		//核心代码!!!
        final Invocation tag = request.tag(Invocation.class);
        final Method method = tag != null ? tag.method() : null;
        final DynamicTimeout timeout = method != null ? method.getAnnotation(DynamicTimeout.class) : null;

        XLog.d("invocation",tag!= null ? tag.toString() : "");

        if(timeout !=null && timeout.timeout() > 0){

            Response proceed = chain.withConnectTimeout(timeout.timeout(), TimeUnit.SECONDS)
                    .withReadTimeout(timeout.timeout(), TimeUnit.SECONDS)
                    .withWriteTimeout(timeout.timeout(), TimeUnit.SECONDS)
                    .proceed(request);
            return proceed;
        }

        return chain.proceed(request);
    }

注意看注释,标注的那3行核心代码.
在Request内,通过tag,获取到Invocation,
然后再获取Invocaion对象的method,最后获取method的注解信息,
判断注解对象存不存在,
如果存在直接读取对应注解对象的设置参数值,动态设置进去.
Wow~
Awesome !!!


拓展

作为一个有追求的程序员,当然会很好奇,
这玩意是怎么实现的 以及 举一反三.
能不能用这个再去做一点其他骚操作,来改善一下我们现有的代码呢?
Invocation
Invocation这个类点进去一看,
平平无奇…
还是去看看他的method属性是怎么设置进去的吧.
RequestFactory
我们在RequestFactory内看到了是如何设置tag,
以及设置进去的tag也就是Invocation对象内如何保存 method和args的.
那么这2个属性的来源呢
Retrofit
当然是来自于Retrofit的核心,这个动态代理方法.
具体的源码分析也不讲了,
网上实在是太多了,我自己在2018年底也写了一篇.

看了一圈,Invocation这个对象是有2个属性的,我们只用到了method,
另外一个args呢,

我们其实也可以拿来利用一下.
比如 一些定义要在header内添加的 sign,user-agent,
可以通过invocation.arguments()获取到,然后进行处理.
这些拓展用法就不细说了.

最后说一句:
JakeWharton牛逼!
JakeWharton


总结

OK,我们回顾完所有的代码,最后的总结就是

通过Invocation动态设置请求超时时间,其原理就是通过在接口请求方法上面添加自定义注解,然后在自定义拦截器内,通过Request的tag,也就是Invocation对象,获取到每一个接口请求方法,判断方法是否存在我们自定义的注解,如果存在那就将注解设置的超时时间动态的设置到chain内.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值