Retrofit源码解读

Retrofit源码解读(一)

文章会用注释的方式来进行解读,同时也是作者(菜鸡)看源码的心路历程
源码基于 retrofit2.6.0

retrofit的建立都是从这里开始

LoginService loginService = retrofit.create(LoginService.class);

那就点进create方法里面看一下

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.单接口代理的创建方式被参数安全所保障
public <T> T create(final Class<T> service) {
    //检查接口里的方法是否规范以及接口是否继承了其他的接口
    Utils.validateServiceInterface(service);
    //validateEagerly == true 提前进行一些预处理操作
    //这些其实看方法名就能看出来,先不深究,先把一套完整的流程弄清楚
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //返回了一个泛型 T 看命名应该是动态代理 传递了三个参数
    //param1:传进来的接口的类加载器,
    //param2:一个class数组 但是retrofit就只穿了你所创建的接口
    /*
        param3:一个InvocationHandler
        是一个接口 跳转过去会有一段注释告诉你:
        这个类是invocation handler的一个代理实例的实现。
        每一个代理实例都与invocation handler有联系。当一个方法被代理实例调用时,
        该方法调用的操作会被编码且分发到他自己的invocation handler的invoke方法中去(渣翻译,可能出错)
        大概就是 把你传进去的接口的方法 都放到一个类里边去实现?这个意思吗?
        不管怎么说 这个类里的invode()方法肯定是关键
        为什么写这么啰嗦,问就是还没了解过动态代理,只是听说过
        todo : 我好菜啊,过完这个就去吧动态代理给弄清楚了。。。
    */
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public @Nullable Object invoke(Object proxy, Method method,
              @Nullable Object[] args) throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            //如果方法来自Object就延迟(?)到一个普通的调用?这两个if应该都是一些检查
            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()方法

//现在出现了一个之前没有出现过的类ServiceMethod,待会儿再看,先看看这个方法干了什么
ServiceMethod<?> loadServiceMethod(Method method) {
    //serviceMethodCache是一个ConcurrentHashMap 看名字就知道这是个缓存。。
    ServiceMethod<?> result = serviceMethodCache.get(method);
    //有缓存,直接返回缓存中的ServiceMethod
    if (result != null) return result;
    //出现了,同步锁,锁住了serviceMethodCache这个对象
    //todo : synchronized 也不是特别清楚,整明白他!
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      //再做一次检查,看是不是已经实例化过了
      if (result == null) {
          //还是没有,自己创建。
          //看方法,解析注释,猜测应该就是解析定义接口时,在接口方法上所添加的@GET @POST 之类的注释了
          //传递的两个参数,一个是当前retrofit对象,还有就是传入的method
        result = ServiceMethod.parseAnnotations(this, method);
        //然后放入缓存。。
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

retrofit2.ServiceMethod类

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //RequestFactory内做了一些注释解析的操作 是一个把retrofit参数转为okhttp3参数的工具类
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
    //然后调用别的类的方法又进行了一次注释解析??迷惑行为,去看看这个方法把
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

HttpServiceMethod.parseAnnotations()方法

//首先,这是一个HttpServiceMethod的构造方法
//这里我删去了一些对kotlin进行兼容的if判断
//这里官方有一个注释,意思是建立一个service method会因为反射有很大的开销,所以最好复用这个service method
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    //callAdapter 斯,这个addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    //emmm 开始了,终于有认识的了
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();

    //这个函数是不是也有点眼熟,addConverterFactory(GsonConverterFactory.create())
    //emmm 有点意思了。
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
    //retrofit.callFactory 返回Retrofit类里边就能轻易发现 这是一个OkHttpClient
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //这里我删了一些对kotlin协程/挂起 的兼容、判断
    //但问题不大,看看CallAdapted这个类干了什么吧
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  }

HttpServiceMethod.CallAdapted类

/**
*   这个类主要是完成一个构造方法类似的工作,初始化一些初值。完成参数传递。构建了一个HttpServiceMethod类
*   直接看下HttpServiceMethod类干了什么吧
*/
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<ResponseT, ReturnT> 类

这个类的代码太多了,就不完整的贴上来了。首先官方对这个类的注释是

  • Adapts an invocation of an interface method into an HTTP call
  • 翻译:把一个接口方法的调用转换进一个Http Call
    同时它还是刚刚ServiceMethod的一个子类,也就是说他实现了ServiceMethod的invoke方法
    不出意外的话,invoke方法的具体实现就在这儿了
    这个是不是和之前提到的动态代理感觉扯得上关系了?
@Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

emmmm OkHttpCall出现了!!
仔细点进去一看。。。。。这个并不是真的OkhttpCall 这个类依旧在retrofit2的包名下
迷惑行为,差点被骗了。
但是再仔细看看
噢噢噢噢哦哦哦哦哦哦哦哦哦哦哦哦哦哦哦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

retrofit2.OkHttpCall类

同样代码太长,就不贴出来了。
这个类实现了retrofit2.Call这个接口,同时也就是这个类完成了retrofit对okhttp的操作
在类中会有一个okhttp3.Call rawCall; 来进行对okhttp的操作;
举个栗子(仅保留关键代码)

@Override public void enqueue(final Callback<T> callback) {
    okhttp3.Call call;
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

好了,到这里就大概对retrofit有了一个了解了

总结

  • retrofit的核心就是大家都知道的动态代理,其实就是那个 Proxy.newProxyInstance的三个参数

1.ClassLoader 类加载器
2.Class<?>[] 这里传入若干接口,newProxyInstance会宣称实现所有传进去的接口,这样你就可以调用这些接口里的方法
3.InvocationHandler 每一个方法都会对应一个自己的InvocationHandler,通过它的invoke()逻辑来实现接口中的方法

  • 对应到retrofit中

第二个参数Class<?>[] 中会传入你定义的接口
传入的接口中的方法最终会由HTTPServiceMethod中的invoke()方法来进行实现。也就是创建一个retrofit2.OkHttpCall<>()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值