Retrofit源码跟读

Retrofit官网

Retrofit的使用如下

1.Retrofit引用--在build.gradle中增加引用

   implementation 'com.squareup.retrofit2:retrofit:2.5.0'  //Retrofit
   implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//返回值转化成json

2.定义接口

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

3.请求

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/") //必须以"/"结尾,不然将抛出异常
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        GitHubService netApi = retrofit.create(GitHubService.class);
        Call<List<Repo>> responseCall = netApi.listRepos("octocat");
        responseCall.enqueue(new Callback<List<Repo>>() {
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
                Log.e(TAG, "onResponse: =" + response.code());
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
                Log.e(TAG, "onFailure: =" + t.toString());
            }
        });

4.结果返回值

 onResponse: =200

按照源码跟读如下:

查看responseCall.enqueue(Callback)方法,得知接口Call的方法,再向上追溯到netApi.listRepos("octocat"),属于接口调用方法返回Call值,再向上追溯retrofit.create(GitHubService.class)
源代码如下:

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(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];

          @Override public Object invoke(Object proxy, Method method, @Nullable 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);
          }
        });
  }

代码核心功能是:

  • 动态代理,调用接口方法时,就是调用new InvocationHandler()对象里的invoke的方法 ,核心就是调用loadServiceMethod(method).invoke(args != null ? args : emptyArgs)
到这里查看Retrofit代码使用,分两部分,一部分是通过Build模式生成Retrofit对象,一部分是使用Retrofit内的create方法,即使用动态代理处理接口的方法

首先我们从通过Build模式建立Retrofit对象开始查看源代码,直接查看build方法

 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
  • 对baseUrl判断是否为null
  • callFactory变量对应的是okhttp3.call.Factory类型,默认初始化的实现是okhttp3的OkHttpClient对象
  • callbackExecutor变量对象的是java.util.concurrent.Executor类型,默认初始化的实现是platform.defaultCallbackExecutor();其中platform通过Build()构造函数知道是在retrofit2.Platform类里实现的是Android内部类,而其中defaultCallbackExecutor()方法返回的是MainThreadExecutor类得知,是通过handler切换线程到主线程
private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
 static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  • callAdapterFactories变量对应的的是retrofit2.CallAdapter.Factory,该变量用来适配网络请求,例如适配RxJava2CallAdapterFactory
  • converterFactories 变量对应的是retrofit2.Converter.Factory,该变量用来适配数据转换,例如适配GsonConverterFactory.create(),其中会有默认的数据解析器 converterFactories.add(new BuiltInConverters());

查看Retrofit类的create(final Class<T> service)方法内的loadServiceMethod(method).invoke(args != null ? args : emptyArgs)

 private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
 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;
  }
  • ConcurrentHashMap是HashMap的一个线程安全的,用来缓存ServiceMethod;根据Method判断是否有缓存,有则直接取出来;否则通过ServiceMethod.parseAnnotations(this, method)重新创建,并缓存起来
abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    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 T invoke(Object[] args);
}
  • RequestFactory.parseAnnotations(retrofit, method)返回的RequestFactory类是注解相关的数据
final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }

  private final Method method;    //方法
  private final HttpUrl baseUrl; //基地址
  final String httpMethod; //请求方法,即get  post  delete
  private final @Nullable String relativeUrl;  //方法的相对地址,即path部分
  private final @Nullable Headers headers;  // 注解的header内容,请求头
  private final @Nullable MediaType contentType; //请求体
  private final boolean hasBody; //是否有请求体
  private final boolean isFormEncoded;  //是否是表单
  private final boolean isMultipart; //是否图片类
  private final ParameterHandler<?>[] parameterHandlers;//方法参数处理器
  • Retrofit不是网络请求框架,是封装的Okhttp的请求框架,通过注解拿到请求参数封装后由okhttp3请求,所以该类是解析各种注解,获取到请求的各种方法;requestFactory是注解的相关参数
  • HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法确定HttpServiceMethod类是ServiceMethod的实现类,包括Invoke方法
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }
  • 构建函数HttpServiceMethod对象的四个变量requestFactory是注解对应的方法及参数,callFactory是Retrofit里对应的OkHttpClient对象
  • callAdapter的创建代码如下:
  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
    Type returnType = method.getGenericReturnType();
    Annotation[] annotations = method.getAnnotations();
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }
  • 首先从网络请求接口方法中获取注释,然后根据注释和注释返回类型,接着调用retrofit.callAdapter()方法从retrofit中获取适配器。咱们跟着代码会发发现其实最后调用的是retrofit的nextCallAdapter()
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
...
  }
  • 在for循环中,根据请求参数在网络适配工厂中创建网络适配器并返回该适配器
  • responseConverter变量的创建代码如下:
  private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
  }

最终还是到Retrofit类中nextResponseBodyConverter方法

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
...
  }
  • 可以看到,和创建网络请求适配器一样的创建方法,根据响应类型和请求方法注释数值,从数据转换器工厂中创建数据转换器并返回
至此loadServiceMethod(method)已完成,创建并返回ServiceMethod的实现类HttpServiceMethod,做的内容包括:解析网络请求接口参数、网络请求适配器、response数据解析器等工作
  • 查看HttpServiceMethod的invoke方法
创建OkHttpCall对象new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)

由于retrofit的网络请求是由okhttp3请求,所以OkHttpCall就是对okhttp的call对象的封装,OkHttpCall对象的同步及异步代码如下:

//网络请求异步操作方法
@Override 
public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    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) {
          t.printStackTrace();
        }
      }

      @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) {
          t.printStackTrace();
        }
      }
    });
  }

//网络请求同步操作方法
  @Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    return parseResponse(call.execute());
  }
  • 不管是同步还是异步,都创建了okhttp3.call rawCall变量,最终调用都是rawCall的同步或者异步方法,也就是okhttp3.Call的enqueue()和execute()
callAdapter.adapt(okHttpCall)

这个方法很显然使用适配器模式,将某些咱们需要处理的事件,适配成其他平台可以使用的类型,并在该平台使用。这里调用serviceMethod的adapt适配方法,传入了上面步骤7中创建的OkHttpCall实例,并将适配对象返回;比如可以使用RxJava2CallAdapterFactory.create()来创建了一个RxJava2CallAdapter的适配器来适配RxJava2平台,适配成RxJava2平台能使用的Call

咱们接下来看Retrofit的CallAdapter接口中的Rxjava2CallAdapter实现类的adapter()方法:
package retrofit2.adapter.rxjava2;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import java.lang.reflect.Type;
import javax.annotation.Nullable;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Response;

final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
  private final Type responseType;


  @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }
}
  • 该适配方法返回了一个Observable被观察者对象
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • 目录介绍 1.首先回顾Retrofit简单使用方法 2.Retrofit的创建流程源码分析2.1 Retrofit...
    杨充211阅读 1,057评论 0 16
  • 一,前言 Retrofit其实是将OKhttp封装起来,和volley一样。那解析Retrofit其实就是解析它如...
    求闲居士阅读 1,329评论 2 5
  • 目录 Retrofit 简介 Retrofit 的具体使用 重点分析 Retrofit 简介 Retrofit 是...
    大豆油阅读 329评论 0 0
  • 适配器模式上一篇文章我们已经分析了Retrofit解析注解封装进ServiceMethod的流程,读者在这里要记住...
    andcoder阅读 652评论 0 2
  • Retrofit这个开源库出来也有一定年头了,记得之前还是在V1.0的版本的时候,之前在三月份也写过一个Retro...
    lovejjfg阅读 1,448评论 0 5