继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Retrofit源码流程解析(一)

喵喔喔
关注TA
已关注
手记 517
粉丝 103
获赞 606

17年就打算好好读下Retrofit的源码的,后来由于种种原因耽搁了,现在终于有时间来写博客记录下自己读源码的总结了。Retrofit是一套网络请求封装库,底层网络请求还是OkHttp,它只是让请求的方式变成接口的描述方式,源码虽然不多,但是是设计模式的典范,里面结合各种设计模式,以及许多优秀的设计思想,非常值得阅读的。

一、环境

Retrofit下载地址,它是用Maven构建的,至于工具,我用Idea工具看的,可以自行去官网下载最新版本查看。导入之后的目录结构是这样的

图片描述

只需要看Retrofit这个Model,其它是Retrofit的扩展。


二、源码执行流程

首先还是从它的调用流程开始看,我们进行网络请求第一步还是创建Retrofit对象,一般创建过程如下:

 Retrofit retrofit = new Retrofit.Builder()
      .baseUrl(BASE_URL)  //BASE_URL为请求的基地址
      .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器为GSON
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //将返回的Response适配到RxJava平台
      .build();

可以看到Retrofit的创建是通过Build构建者模式创建,一般会为它设置BASE_URL,ConverterFactory,CallAdapterFactory ,我们点进去看的build()方法,

 public Retrofit build() {   if (baseUrl == null) {  //从这里可以看到baseUrl是必须设置的,不设置就会抛异常
     throw new IllegalStateException("Base URL required.");
   }

   okhttp3.Call.Factory callFactory = this.callFactory; 
   if (callFactory == null) {
     callFactory = new OkHttpClient();  //这里的callFactory不设置默认为OkHttpClient,callFactory也就是你真正发请求的工厂类
   }

   Executor callbackExecutor = this.callbackExecutor;   if (callbackExecutor == null) {
     callbackExecutor = platform.defaultCallbackExecutor();  //里面封装的是Handler,用它来做异步切换的
   }   //设置的CallAdapterFactory添加到List集合中,第一步会添加我们设置的,后面才会添加一个默认的defaultCallAdapterFactory。
   List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
   adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));   //设置的ConverterFactory添加到List集合中,第一步会添加一个默认的BuiltInConverters,后面才会添加我们设置的。
   List<Converter.Factory> converterFactories =       new ArrayList<>(1 + this.converterFactories.size());
   converterFactories.add(new BuiltInConverters());
   converterFactories.addAll(this.converterFactories);    //创建我们的retrofit对象
   return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
       callbackExecutor, validateEagerly);
 }

在看这段代码时候里面会有一个Platform,它是一个平台类,通过实现它,用来适配不同平台。

class Platform {  private static final Platform PLATFORM = findPlatform();  static Platform get() {    return PLATFORM;
  }  private static Platform findPlatform() {    try {
      Class.forName("android.os.Build");      if (Build.VERSION.SDK_INT != 0) {        return new Android();  //从这里可以看出默认的平台就是Android平台
      }
    } catch (ClassNotFoundException ignored) {
    }
  }

... //省略部分代码
  
  static class Android extends Platform {    @Override public Executor defaultCallbackExecutor() {      return new MainThreadExecutor();
    }    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {      if (callbackExecutor == null) throw new AssertionError();      return new ExecutorCallAdapterFactory(callbackExecutor);
    }    static class MainThreadExecutor implements Executor {      private final Handler handler = new Handler(Looper.getMainLooper());      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
}

从这段代码中可以看出Platform可以适配不同平台,默认给我们适配的平台就是Android,我们前面调用platform的方法都是调用它的Android子类里面的方法。看下它里面的方法

defaultCallbackExecutor()方法里面就是持有MainThreadExecutor 的实例对象,而MainThreadExecutor里面封装了一个Handler,它通过Looper.getMainLooper()让其运行在主线程,由于它的权限级别是私有的,它通过调用execute()方法来进行线程切换。

defaultCallAdapterFactory() 就是默认的CallAdapterFactory刚刚在CallAdapterFactories集合里面添加的就是这个,这个很重要待会要用到,需要看里面的实现

到了这一步Retrofit的创建就完成了。下一步就是传入接口方法获取其实例对象

//Github就是你在项目中的接口,里面是所有网络请求的接口描述GitHub github = retrofit.create(GitHub.class);

我们点进去看create()方法

 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();

         @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
             throws Throwable {
           ... //省略部分代码
           ServiceMethod<Object, Object> serviceMethod =
               (ServiceMethod<Object, Object>) loadServiceMethod(method);
           OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);           return serviceMethod.callAdapter.adapt(okHttpCall);
         }
       });
 }

里面是用了动态代理设计模式,返回的对象只是其代理对象。所有我们调用接口对象的方法都会走这段代码。逐行看代码

ServiceMethod<Object, Object> serviceMethod =
               (ServiceMethod<Object, Object>) loadServiceMethod(method);

首先调用loadServiceMethod()方法,通过它获取一个ServiceMethod实例,这个实例封装了网络接口方法的描述,首先看loadServiceMethod的实现

ServiceMethod<?, ?> loadServiceMethod(Method method) {
  ServiceMethod<?, ?> result = serviceMethodCache.get(method);  if (result != null) return result;

  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);    if (result == null) {
      result = new ServiceMethod.Builder<>(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }  return result;
}

ServiceMethod是缓存到了一个Map中,首先会通过Map获取其实例,如果Map中有其实例,就直接返回,否者创建一个缓存到Map中,然后返回。

ServiceMethod的创建也是通过构建者模式,看下build()实现

public ServiceMethod build() {
  callAdapter = createCallAdapter();  //创建callAdapter
  ... 
  responseConverter = createResponseConverter();  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);   //方法注解
  }  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    ...
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }  return new ServiceMethod<>(this);
}

可以看出ServiceMethodbuild()方法里面主要做的事情是callAdapterresponseConverter实例的获取,以及解析方法注解,我们来看下callAdapter的实例是怎么获取的

private CallAdapter<T, R> createCallAdapter() {
  Type returnType = method.getGenericReturnType();
  ...
  Annotation[] annotations = method.getAnnotations();  try {    //noinspection unchecked
    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(e, "Unable to create call adapter for %s", returnType);
  }
}

可以看出还是要调用retrofitcallAdapter方法

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {  return nextCallAdapter(null, returnType, annotations);
}  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    ...
    int start = adapterFactories.indexOf(skipPast) + 1;    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);      if (adapter != null) {        return adapter;
      }
    }
   ...

代码片段省略了部分,最后还是会走到nextCallAdapter方法去获取其实例,callAdapter实例会从adapterFactories获取,由于获取的是一个工厂类还是要调用一个get方法从工厂获取其callAdapter对象。adapterFactories就是我们获取Retrofit实例时候传入的,可以自定义,也可以用别人提供的,先设置的满足条件,先会被使用。

responseConverter也是一样的方法去获取其实例。

这部分完了,再回到代理方法里,接着创建了一个OkHttpCall实例

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

接着调用这句

serviceMethod.callAdapter.adapt(okHttpCall);

callAdapter是获取retrofit实例设置的,如果我们没用RxJava,接口方法的返回值为Call,那么这个callAdapter获取的实例是这个

adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

这个刚才说了,也就是Platform的子类Android,也就是ExecutorCallAdapterFactory,也就是说最后会调用其adapt方法

@Override public Call<Object> adapt(Call<Object> call) {  return new ExecutorCallbackCall<>(callbackExecutor, call);
}static final class ExecutorCallbackCall<T> implements Call<T> {
 ... @Override public void enqueue(final Callback<T> callback) {
   checkNotNull(callback, "callback == null");

   delegate.enqueue(new Callback<T>() {     @Override public void onResponse(Call<T> call, final Response<T> response) {
       callbackExecutor.execute(new Runnable() {         @Override public void run() {           if (delegate.isCanceled()) {             // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
             callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
           } else {
             callback.onResponse(ExecutorCallbackCall.this, response);
           }
         }
       });
     }     @Override public void onFailure(Call<T> call, final Throwable t) {
       callbackExecutor.execute(new Runnable() {         @Override public void run() {
           callback.onFailure(ExecutorCallbackCall.this, t);
         }
       });
     }
   });
 } @Override public Response<T> execute() throws IOException {    return delegate.execute();
  }

adapt是返回一个ExecutorCallbackCall的实例,它是call的子类,然后我们会调用enqueue去做网络请求,它是异步的,或者调用execute做网络请求,它是同步的。在调用的时候,里面都是走的是delegate代理类,也就是OkHttpCallOkHttpCall后面再单独看)里面的方法,里面还是通过OkHttp发送的网络请求,请求成功或者失败会回调okHttp的回调,由于它的回调是异步的,接着调用callbackExecutor.execute将线程从子线程切换到主线程,然后调用callback.onResponse或者callback.onFailure做回调,也就是我们常用Retrofit发网络请求的回调。这时候代码也就是运行到了主线程。


三、总结

代码到了这里,一次完整的网络请求也就完毕了,这只是流程的讲解,详细代码细节后面再单独介绍。

推荐参看:
1、Android:手把手带你深入剖析 Retrofit 2.0 源码
2、 这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

原文链接:http://www.apkbus.com/blog-801322-77605.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP