Retrofit 原理解析与自定义实现详解手机开发

Retrofit 结合OkHttp构成了当前非常流行的Android的网络框架。而Retrofit对OKHttp进行了一层封装,可能入手的门槛高一点,但是使用习惯以后可以说是非常的简洁和高效。

Retrofit 还可以跟 Rxjava 转化成Obserable,形成了链式编程风格,深得我心。

Retrofit的基本源码流程:

  1. 动态代理获取Method
  2. Method从提取出注解参数
  3. 执行网络操作
  4. 转换成对应结果

本文不会直接跟着代码走完所有流程,只拿出重要的几点分析。

在开始分析之前,先写个简单的例子,我们申明一个接口 getServiceName

public interface ServiceApi {
    
	@GET 
	Call<String> getServiceName(); 
} 

下面来看,Retrofit 如何解析ServiceApi并进行网络操作。

Retrofit类定义了几个重要的变量:

  // Retrofit 
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); 
  final okhttp3.Call.Factory callFactory; 
  final HttpUrl baseUrl; 
  final List<Converter.Factory> converterFactories; 
  final List<CallAdapter.Factory> callAdapterFactories; 
  final @Nullable Executor callbackExecutor; 

Retrofit的第一步就是获取

  • ServiceMethod对应着根据Method解析出的注解、返回的结果类型等,并缓存到了serviceMethodCache,避免每次都需要重新解析

  • callFactory 是okhttp创建call的类

  • baseUrl

  • converterFactories 是一个集合,负责对网络请求的RequestBody 和网络请求结果 ResponseBody的转换,例如我们经常使用的GsonConverterFactory

  • callAdapterFactories 也是一个集合,负责对最后的返回结果的封装或转换,例如我们经常使用的RxJava2CallAdapterFactory

  • callbackExecutor 是负责执行,Android默认执行器是利用handler抛到主线程执行回调结果。所以我们会看到retrofit的结果都在主线程中。

1. 动态代理获取Method

retrofit之所以利用动态代理,有两个目的:

  1. 可以实例化上面ServiceApi这个接口,直接调用getServiceName进行网络请求;
  2. 可以通过动态代理拿到对应的Method,也就可以拿到Method上的注解,进行参数解析;

除了这种动态代理的实现方式以外,要想达到一样的效果的就是类似ButterKnife注入框架,在编译时候利用AnnotionProcessor生成ServiceApi实现类。因为是编译期生成,所以不会影响运行效率,但是也会存在其他问题。

public <T> T create(final Class<T> service) {
    
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] {
    service }, 
        new InvocationHandler() {
    
          private final Platform platform = Platform.get(); 
          private final Object[] emptyArgs = new Object[0]; 
 
          public Object invoke(Object proxy, Method method, 
              Object[] args) throws Throwable {
    
            // If the method is a method from Object then defer to normal invocation. 
            if (method.getDeclaringClass() == Object.class) {
    
              return method.invoke(this, args); 
            } 
            if (platform.isDefaultMethod(method)) {
    
              return platform.invokeDefaultMethod(method, service, proxy, args); 
            } 
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 
          } 
        }); 
  } 

这里直接看最后的一句:

loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 

2. Method从提取出注解参数

ServiceMethod<?> loadServiceMethod(Method method) {
    
    // 直接从缓存获取 
    ServiceMethod<?> result = serviceMethodCache.get(method); 
    if (result != null) return result; 
 
    synchronized (serviceMethodCache) {
    
      result = serviceMethodCache.get(method); 
      if (result == null) {
    
        // 解析注解参数 
        result = ServiceMethod.parseAnnotations(this, method); 
        serviceMethodCache.put(method, result); 
      } 
    } 
    return result; 
  } 

parseAnnotations()的作用:

  1. 解析注解转换成各种http参数
  2. 解析出返回类型Type
  3. 找出对应的CallApater
  4. 找出对应的Converter
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( 
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; 
    boolean continuationWantsResponse = false; 
    boolean continuationBodyNullable = false; 
 
    Annotation[] annotations = method.getAnnotations(); 
    Type adapterType; 
    if (isKotlinSuspendFunction) {
    
      Type[] parameterTypes = method.getGenericParameterTypes(); 
      Type responseType = Utils.getParameterLowerBound(0, 
          (ParameterizedType) parameterTypes[parameterTypes.length - 1]); 
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
    
        // Unwrap the actual body type from Response<T>. 
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); 
        continuationWantsResponse = true; 
      } 
 
      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType); 
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); 
    } else {
    
      adapterType = method.getGenericReturnType(); 
    } 
 
    CallAdapter<ResponseT, ReturnT> callAdapter = 
        createCallAdapter(retrofit, method, adapterType, annotations); 
    Type responseType = callAdapter.responseType(); 
     
    ... 
 
    Converter<ResponseBody, ResponseT> responseConverter = 
        createResponseConverter(retrofit, method, responseType); 
 
    okhttp3.Call.Factory callFactory = retrofit.callFactory; 
    if (!isKotlinSuspendFunction) {
    
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); 
    } else if (continuationWantsResponse) {
    
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. 
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory, 
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); 
    } else {
    
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. 
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory, 
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, 
          continuationBodyNullable); 
    } 
  } 

3. 执行网络操作

loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 

ServiceMethod.invoke()进行了网络操作和转换操作,不过他是个抽象方法,直接看他的子类HttpServiceMethod

// HttpServiceMethod 
 final @Nullable ReturnT invoke(Object[] args) {
    
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); 
    return adapt(call, args); 
  } 
 
  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args); 

具体看CallAdapted实现类,他就是一个封装类,封装了CallAdapter。

转发调用了CallAdapter的adapt,这里的CallAdapter是由上面parseAnnotations()中找出对应的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); 
    } 
} 

callAdapter.adapt()根据不同的具体callAdapter执行不同的操作。

其中默认的实现也只是执行了Okhttp的Call.enque()流程。

再回来看HttpServiceMethod 的invoke()方法,内部主要是构造了一个retrofit2.OkHttpCall对象,里面封装了OkHttp 的Call对象、Converter,其实就是封装了整个Okhttp的请求流程,最后对Converter结果转换。

这里不贴代码了。

实现一个简单的Retrofit框架

自定义Retrofit 需要做到:

  1. 动态代理
  2. 解析参数
  3. 执行操作和转换结果,返回对应类型的结果

定义一个参数注解

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

CustomParam就是最简单的一个注解参数,value是一个整数,对应着是Retrofit各种复杂网络参数配置。

定义一个执行者CallAdapter接口

public abstract class CustomCallAdapter<P, R> {
    
    public abstract R adapt(P params); 
 
    public abstract Type getResponseType(); 
} 

CustomCallAdapter是一个CallAdapter的简化版本,内部负责调用和返回结果类型。用户可以自定义实现CallAdapter

定义一个CustomRetrofit

public class CustomRetrofit {
    
    // 存储各种自定义的CallAdapter 
    private List<CustomCallAdapter> mCallAdaters; 
 
    private CustomRetrofit() {
    
        mCallAdaters = new ArrayList<>(); 
    } 
 
    private <T, R> void addCalladapter(CustomCallAdapter<T, R> callAdapter) {
    
        mCallAdaters.add(callAdapter); 
    } 
 
    public <T> T create(Class<T> cls) {
    
        return (T) Proxy.newProxyInstance(cls.getClassLoader(), new Class[]{
   cls}, 
                new InvocationHandler() {
    
                    @Override 
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                        return convert(method); 
                    } 
                }); 
    } 
 
    // 真正的执行 
    private Object convert(Method method) {
    
        Type type = method.getReturnType(); 
        // 根据需要的返回类型找出CallAdapter 
        CustomCallAdapter callAdapter = getCallAdapter(type); 
        if (callAdapter == null) {
    
            throw new RuntimeException("no callAdapter"); 
        } 
        // 解析参数 
        CustomParam param = method.getAnnotation(CustomParam.class); 
        int value = param == null ? 0 : param.value(); 
        // callAdatper执行(忽略了最后结果转换这一步) 
        return callAdapter.adapt(value); 
    } 
 
    private CustomCallAdapter getCallAdapter(Type type) {
    
        for (CustomCallAdapter item : mCallAdaters) {
    
            if (type == item.getResponseType()) {
    
                return item; 
            } 
        } 
        return null; 
    } 
    // 简单的builder模式 
    public static class Builder {
    
        private CustomRetrofit instance = null; 
 
        public Builder() {
    
            instance = new CustomRetrofit(); 
        } 
 
        public Builder addCallAdapter(CustomCallAdapter callAdapter) {
    
            instance.addCalladapter(callAdapter); 
            return this; 
        } 
 
        CustomRetrofit build() {
    
            return instance; 
        } 
    } 
} 

上面的注解很简单和清晰了,不做过多解释。

使用

public interface SimpleApi {
    
    @CustomParam(2) 
    Integer test(); 
} 
public class SimpleCallAdapter extends CustomCallAdapter<Integer, Integer> {
    
 
    @Override 
    public Integer adapt(Integer param) {
    
        return param; 
    } 
 
    @Override 
    public Type getResponseType() {
    
        return Integer.class; 
    } 
} 

测试一下

    @Test 
    public void testRetrofit() {
    
        CustomRetrofit retrofit = new CustomRetrofit.Builder() 
                .addCallAdapter(new SimpleCallAdapter()) 
                .build(); 
 
        int result = retrofit.create(SimpleApi.class).test(); 
 
        System.out.println(result); 
    } 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/app/6261.html

(0)
上一篇 2021年7月17日 00:45
下一篇 2021年7月17日 00:45

相关推荐

发表回复

登录后才能评论