【开源库学习】从OkHttp到Retrofit(其二 Retrofit)

简单使用

class RetrofitActivity : AppCompatActivity() {
    companion object {
        const val SERVER = "https://www.xxx.com/"
    }
    var disposable:Disposable? = null;
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_retrofit)
        val retrofit = Retrofit.Builder()
        .baseUrl(SERVER)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build()
        disposable = retrofit.create(TestApi::class.java).getIcons(1).subscribe(
            {
                Log.d("api", it.isSuccessful.toString())
            }, {
                Log.d("api", it.toString())
            })
    }

    override fun onStop() {
        super.onStop()
        disposable.dispose()
    }
}

//RESTFUL 风格接口
interface TestApi {
    @GET("/test/icon")
    fun getIcons(
        @Query("icon_id") icon_id: Long
    ): Observable<Response<IconBean>>
}

class IconBean{}

实现原理

retrofit
Retrofit的代码逻辑比较复杂,但是实际上Retrofit的主要功能就是给OkHttp做一层封装,这里我把主要流程进行了总结,简单来说当调用Retrofit.create(TestApi.classjava)方法之后,Retrofit首先会判断TestApi这个类是否符合条件,如果开启了严格检查的话,还会提前加载HttpServiceMethod。

//Retrofit.java
public <T> T create(final Class<T> service) {
    //验证
    validateServiceInterface(service);
    return (T)
        //动态代理
        Proxy.newProxyInstance(
        service.getClassLoader(), 
        new Class<?>[] {service}, 
        new InvocationHandler() {
            //判断android和jvm平台及其版本
            private final Platform platform = Platform.get();

            @Override
            public Object invoke(Object proxy, Method method, Object[] args){
                //如果是静态方法则直接执行
                if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                }
                //isDefaultMethod:是否是默认方法
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args); 
            }
        });
}
private void validateServiceInterface(Class<?> service) {
	//判断是不是接口,不是就抛出异常
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
	//判断存不存在泛型,存在则抛出异常
    Deque<Class<?>> check = new ArrayDeque<>(1);
    check.add(service);
    while (!check.isEmpty()) {
      Class<?> candidate = check.removeFirst();
      if (candidate.getTypeParameters().length != 0) {
        StringBuilder message =
            new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
        if (candidate != service) {
          message.append(" which is an interface of ").append(service.getName());
        }
        throw new IllegalArgumentException(message.toString());
      }
      Collections.addAll(check, candidate.getInterfaces());
    }
	//提前加载
    if (validateEagerly) {
      Platform platform = Platform.get();
      for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
          loadServiceMethod(method);
        }
      }
    }
  }

loadServiceMethod

当检查完成之后,Retrofit就会创建出一个代理类,因此调用retrofit.create(TestApi::class.java).getIcons(1)事实上是调用了代理类的invoke方法,这个invoke方法会首先根据注解进行解析,添加参数,生成一个okHttp的Call请求,然后通过适配器模式将Call的返回结果进行适配。例如我希望使用RxJava的Observable作为返回类型,那么这里可以使用RxJavaCallAdapterFactory将OkHttp返回的Call<T>类型转换为Observable<T>
基于这个流程,来阅读一下代码。

ServiceMethod<?> loadServiceMethod(Method method) {
	//判断是否有缓存
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      	//没有缓存的话根据注解解析一个
      	//这里的返回是一个HttpServiceMethod,里面包含了一个适配好的call
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
//ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    //检查:articleList方法返回类型不能用通配符和void...
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

可以看到ServiceMethod中首先创建了一个RequestFactory,RequestFactory的作用是根据注解来

//RequestFactory.java
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
}

class Builder {
    RequestFactory build() {
        //解析请求类型,methodAnnotations是method中的注解,通过getAnnotations()获取
        for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
        }
		//...
        //解析参数注解如Path,parameterAnnotationsArray是参数注解数组
        int parameterCount = parameterAnnotationsArray.length;
        parameterHandlers = new ParameterHandler<?>[parameterCount];
        for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
        }
        //... 
        return new RequestFactory(this);
    }
}

从这里可以看出当build方法调用之后,事实上RequestFactory对传入的方法完成了解析,并且把解析的结果保存在自己成员变量中。

//HttpServiceMethod.java
//ResponseT响应类型如WanArticleBean,ReturnT返回类型如Call
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //...
    Annotation[] annotations = method.getAnnotations();
    //遍历找到合适的适配器
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    //得到响应类型
    Type responseType = callAdapter.responseType();
    //根据返回类型找到合适的转换器
    //最终又会回调到retrofit里面的callAdapterFactories
   	//callAdapterFactories在一开始builder时候传入
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
    //父类HttpServiceMethod中的实现。
	 @Override
	  final @Nullable ReturnT invoke(Object[] args) {
	    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
	    return adapt(call, args);
	  }
  }

结合之前的说明,可以看到当找到和是的适配器之后,loadServiceMethod会返回一个CallAdapted,并且当调用invoke方法时候,会根据CallAdapted内部的callAdapter,将Call转化为适配类型。
callAdapter又是从retrofit的callAdapterFactories中遍历得到,所以这里再回过来看看retrofit.builder()方法。

//Retrofit.Builder.java
public Retrofit build() {
    Executor callbackExecutor = this.callbackExecutor;
    //如果没设置线程池,则给android平台设置一个默认的MainThreadExecutor(用Handler将回调切回主线程)
    if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
    }
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    //添加默认的DefaultCallAdapterFactory
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
    	//默认的只有两个,如果需要使用其他的AdapterFactory需要在创建的时候传入
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

Converter

Converter的作用就是转化各种参数类型。

interface WanApi {
    //Long cur 当前时间
    @GET("article/list/{page}/json")
    Call<WanArticleBean> articleList(@Path("page") int page, @Query("cur") Long cur);
}

class TimeConverter implements Converter<Long, String> {
    private SimpleDateFormat mFormat = new SimpleDateFormat("yyyy-MM-dd-HHmmss");

    @Override
    public String convert(Long value) throws IOException {
        if (value > 1_000_000_000_000L) {//毫秒,不是很严谨 - -
            return mFormat.format(new Date(value));
        }
        return String.valueOf(value);
    }
}

class TimeConverterFactory extends Converter.Factory {

    @Override
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (type == Long.class) {
            //使用自定义TimeConverter
            return new TimeConverter();
        }
        return super.stringConverter(type, annotations, retrofit);
    }

    public static Converter.Factory create() {
        return new TimeConverterFactory();
    }
}

//addConverterFactory(TimeConverterFactory.create())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值