android基础复习笔记——4.retrofit的使用、原理、源码解析,及rxjava的接入(模拟第一次读源码的场景)

源码怎么读?
拆成大块读,你从粗到细读。
先写示例,然后跟着示例点到源码里面去,然后一步一步分析retrofit是怎么工作的。
一定要跟着一步一步走下去,动手写示例,跳链接,写演示代码。

1.什么是retrofit?

这是一个http的库,他是给android用,也可以给java后端用。之前他是给android用的,后来慢慢地做得足够散,足够的轻,足够的接口化,现在是android和java都可以用他了。

2.怎么用?

简单说一下怎么用,毕竟有人没用过。
看官网https://square.github.io/retrofit/
1.首先你要去做一个interface,这个interface声明了你的所有api的调用。就是http请求大概什么样的,你通过这些方法声明来描述出来,你不需要写出具体的url。
在这里插入图片描述

2.创建一个retrofit的对象,再用这个对象创建出对象具体的interface实例,谁的实例?就是上面GitHubService的实例,就是你的接口列表的实例,这个接口列表包含你的所有接口。
在这里插入图片描述

3.你用这个接口进行网络的调用。
在这里插入图片描述

以官网为例子大致写一下怎么用。
1.首先把这个retrofit加进来,添加依赖

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

2.创建一个名字为GithHubService的interface。然后声明一个get请求,这个格式不用背,用着就熟了,把请求路径填进去

public interface GitHubService {
    @GET("users/renwuxian/repos")
    Call<ResponseBody> getRepos();
}

3.创建retrofit对象,调用api

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com")
                .build();

        GitHubService api =retrofit.create(GitHubService.class);

        api.getRepos().enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                System.out.println("success!");
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });//异步的
//        api.getRepos().execute();//同步的

4.添加权限

<uses-permission android:name="android.permission.INTERNET"/>

5.返回的是一个OKhttp的ResponseBody,所以需要做一个转换,添加一个转化器工厂,这个需要加json的支持

implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

添加转化器工厂

Gson gson = new Gson();
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

6.这样接口申明里面就可以把ResponseBody改成json串对应的bean类了。

@GET("users/renwuxian/repos")
Call<ResponseBody> getRepos();
⬇️
@GET("users/renwuxian/repos")
Call<BaseBean> getRepos();

对应的返回也要改,最后把结果打印出来

api.getRepos().enqueue(new Callback<BaseBean>() {
    @Override
    public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {
        System.out.println("success!"+gson.toJson(response.body()));
    }

    @Override
    public void onFailure(Call<BaseBean> call, Throwable t) {

    }
});

3.源码从头到尾大致分析一下

读源码不能一行一行读下来,从一个入口开始,从程序最直接交互的那个口—>enqueue
我们知道enqueue是用来做网络请求的,如果我看懂了enqueue,是不是前面的东西都不用懂?
有可能你的项目超级大,假如他有一个核心的配置,比如Retrofit,我从这点进去看,可能会给我一个过于宏大的场景了。
我从最直接的来看,也许你这个框架有8个功能,我从一个功能看,慢慢往别的地方去扩展。

enqueue做什么的?他是去后台去执行我们的网络请求,enqueue在retrofit里面不是把每一个请求按照顺序去执行。而是执行这个方法以后,你的请求就会扔到他的列表里面,然后列表里面的东西马上就会被执行了,比如你有8个请求,这8个请求就一起执行了,并不会等某个请求结束。这个东西有什么作用呢?你立即执行为什么还要用队列啊?他会记录一下你同时运行的请求数,如果请求数太多了(大概是64个),他为了性能会给你停一停,别的新加进去的,我不会让他直接去执行了,先排着队,等别的让出位置了,让出足够的性能空间了,比如cpu,你们再去做。

1.找到入口:create()

看源码:
enqueue点进去,这是一个抽象方法,再看位置,连个类都不是,他是一个接口,叫做Call。那现在完了,我不知道这个enqueue是怎么执行的,因为他是一个接口里面的抽象方法。
那怎么办呢?我要知道他所在的这个对象当初是怎么创建的,也就是这个getRepos()他是怎么被创建的。
但是getRepos()所在的api对象是GitHubService,他是一个我们刚刚声明的接口。那我们就去看这个api对象是怎么创建的。

GitHubService api =retrofit.create(GitHubService.class);

retrofit.create他是怎么做的?如果create里面还是接口的话,我得再链,如果没有的话就很好。点进去,太好了,终于是一个可以让我看的代码了。
这create做了什么事情呢?他创建了接口对象,这个接口是所有包含了你网络定义api的接口,create是项目的核心,所有东西都是从这来的。

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

        @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);
          }
          ServiceMethod<Object, Object> serviceMethod =
              (ServiceMethod<Object, Object>) loadServiceMethod(method);
          OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.adapt(okHttpCall);
        }
      });
}

继续读代码,第一行

Utils.validateServiceInterface(service);

点进去看一下。他是做验证的,做了两个验证,第一,你传进来的参数要是一个interface,第二,他的继承的接口不能大于0,这代表他必须是一个土生土长的接口,不能是继承了别的接口

static <T> void validateServiceInterface(Class<T> service) {
  if (!service.isInterface()) {
    throw new IllegalArgumentException("API declarations must be interfaces.");
  }
  // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
  // Android (http://b.android.com/58753) but it forces composition of API declarations which is
  // the recommended pattern.
  if (service.getInterfaces().length > 0) {
    throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
  }
}

不用管它,不是关键点,同样的下面这一行,如果你做了激进化的配置的话,你就去验证一下,大致就是对你写的接口GitHubServic的合法性进行及早的验证。
为什么要做这个配置呢?假如你做了这个配置,在你的Service被创建的一瞬间,就把所有的验证都做完了,那么他很利于你的调试工作,很早就发现你的代码写的不对,但不利于性能。retrofit实际运行过程中,你用到什么方法,他就会稍微卡一瞬间,但是你卡一下没关系,你这卡一下那卡一下就分摊了,所以正式的项目中你不能这么做,不能让他过早的验证。因为过早的验证会导致集中验证。会被用户明显的知道卡一下。所以也不是关键点,这两个都是检查。

if (validateEagerly) {
  eagerlyValidateMethods(service);
}

关键是这个,这么一行代码,这个newProxyInstance里面填了三个参数,其中第三个参数超长。

  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 {
          // 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);
          }
          ServiceMethod<Object, Object> serviceMethod =
              (ServiceMethod<Object, Object>) loadServiceMethod(method);
          OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.adapt(okHttpCall);
        }
      });

newProxyInstance这个方法是什么?这个地方是动态代理。

三个参数,第一个参数是classloader,classloader可以理解为你要创建新的类的时候,你都要提供一个类加载器,来把这个类加载进来,不管这个类是你之前写过的,还是现场定义的一个类。所以这个classloader你不需要做任何工作, 你只需要把他拿出来,这个参数不用管,他就是说你给我提供一个classloader。你就随便扔一个吧,就把我所处的classloader给她。

第二个参数是你提供一系列的接口,你提供 一系列的interface,我这个newProxyInstance就会把所有的接口实现到一个对象里面。不过retrofit只提供了一个interface,就是装着我们所有api方法调用的那个接口。这个也好理解,但是你是怎么实现的呢?你是怎么把那些我声明了但是从来没有在任何地方实现的东西,你给我实现了?

关键在哪呢?关键在第三个参数。这个东西是什么?他是一个对象,对象里面有一个方法,叫做invoke的方法, 你传过来一个对象,对象里面有一个方法,他实际上是什么?实际上是一个回调。什么是回调?你把这个东西给我传过来,我先放着,等会我需要用了,我调用一下。那么这个方法里面的东西就是我们的关键点,但是我们现在先不说,我先说一下这个newProxyInstance他做什么事情。用代码说明一下做了什么。

创建一个类,叫做RealService

public class RealService implements GitHubService {
    @Override
    public Call<BaseBean> getRepos() {
        return null;
    }
}

这里就做到第一步了,我实现了service,第二步是,怎么做到自动的呢?他把InvocationHandler传过来了,我把他复制过去。忽略报红的部分,假装他是可以用的。然后修改了getRepos方法。这个newProxyInstance实际上就是做的这个事情。

第一,他会创建一个对象,这个对象是实现了你给我的所有接口,
另外,他的每个方法我都会实现,通过调用我的invocationHandler的invoke方法,把你这个方法的方法信息给装进去,他实际上就是做的这么一个事情。

public class RealService implements GitHubService {
    InvocationHandler invocationHandler =  new InvocationHandler() {
        private final Platform platform = Platform.get();

        @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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
        }
    };
    @Override
    public Call<BaseBean> getRepos() {
        Method method = null;
        try {
            method = GitHubService.class.getMethod("getRepos");
            return (Call<BaseBean>)invocationHandler.invoke(this,method,null);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

接下来我要知道invoke里面做了什么事情,我就知道retrofit是怎么做的了。
你怎么就把我的方法给实现了?你交给他的代理,那个handler他又做了什么事情呢?
看里面

@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);
    }
    ServiceMethod<Object, Object> serviceMethod =
            (ServiceMethod<Object, Object>) loadServiceMethod(method);
    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.adapt(okHttpCall);
}

首先这三行,
什么是DeclaringClass?就是你是在哪个类里面声明的这个方法,一个类里面的所有方法,只要他能调用的,要么是他申明的,要么是他的父类申明的。
这里就是说,如果这个方法是object声明的,那我就直接调用。意思就是这个方法不是申明在GitHubService里面的话,比如一个toString()、hashCode()等等,那么你怎么申明的怎么用,我不改写你。简单说没有用,他就是保证我的代码不出错。

if (method.getDeclaringClass() == Object.class) {
    return method.invoke(this, args);
}

然后这几个也是。首先我要知道platform是什么?他做了什么?

if (platform.isDefaultMethod(method)) {
    return platform.invokeDefaultMethod(method, service, proxy, args);
}

看platform的创建过程,get方法点进去

 private final Platform platform = Platform.get();

findPlatform(),这个方法没有任何描述,再点,有一个android的,一个java8,还有一个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();
    }
  } catch (ClassNotFoundException ignored) {
  }
  try {
    Class.forName("java.util.Optional");
    return new Java8();
  } catch (ClassNotFoundException ignored) {
  }
  return new Platform();
}

然后回去,这个方法就是看他是不是一个接口的默认方法,什么叫DefaultMethod?这是java8开始的一个新特性。我们都知道Java的interface是不能直接实现的,你的所有方法必须要让具体实现的那个类去实现, 你不能给出默认实现。而java8允许了。就这样,没别的了。这个东西对retrofit来说是没有用的,因为我们的接口都是不实现的。这个也没用。

if (platform.isDefaultMethod(method)) {
    return platform.invokeDefaultMethod(method, service, proxy, args);
}

2.找到核心的三行代码

最后这三行就是retrofit实际做的事情了。那么又有问题了,这三行我都不认识,什么叫serviceMethod?什么叫okHttpCall?什么叫adapt?这三行我都想知道,我都看不懂,怎么办呢?我读代码的时候,需要找一唯一入口,因为有一个入口我能够更快的读懂一个完整的小事件,这个时候我有一个完整的方案,这个时候我的脑袋里面就可以清空一些内存出来,能继续读,那么现在有三行怎么办呢?我选谁呢?而且看起来也不知道谁更重要。而且他们彼此之间都有联系。这个时候我会选择每个都大致看一下,然后去判断我应该先细看谁。肯定要细看的,但是东西比较多的时候,我要大致浏览一下看我先看谁。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

3.粗读ServiceMethod

ServiceMethod点进来,有点蒙,文件也很大,看他的注释,把一个interface方法的调用适配到一个http的call(/** Adapts an invocation of an interface method into an HTTP call. */)。
这句话大致没毛病,但是要我把他和代码联系起来我就联想不起来,我知道你在说什么但是我完全理解不了。

在这我首先解释一个东西,什么叫adapter?我们平时做安卓开发会用到各种adapter,但是可能对什么叫adapter,什么是适配器没有足够的了解。适配器就是做转接的,就是把两孔的插头转成三孔。他把一个一个interface method适配到了一个http call。他是什么意思,就是把我们定义的api对应到一个http的call。不过这是我的猜测。这个时候你要问我这个方法是怎么用的我还是不知道。 注释讲的很少,代码也很长,拐回去,看看别的地方。

loadServiceMethod方法,我看看能不能把他看懂。又要链了,这一段东西是一个cash,我怎么知道的?

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;
}

serviceMethodCache的声明是一个Map,用Map来做cash非常常用。我这有没有这个东西呢?我这是否生成过,是否产生过这个东西呢?如果产生过,我的map里面能够查找到,那么我就直接用他,如果没有,我去生成一下,然后添加进来。

private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

cash是这么一个工作原理,那么我需要去看他是在哪做的生成。点开Builder,看我能不能看懂。

result = new ServiceMethod.Builder<>(this, method).build();

两个参数,一个是Retrofit,Retrofit是什么我也不知道,大致感觉上是一个总管的配置。还有一个是method,我定义在api里面的方法。

Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();
  this.parameterTypes = method.getGenericParameterTypes();
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}

参数好像也不多,接下来他会做三行
一个是从他的方法取到每一个注解
第二,取到他方法参数的每一个类型
第三,取到方法参数的每一个注解(一个参数是可以加多个注解的)

  this.methodAnnotations = method.getAnnotations();
  this.parameterTypes = method.getGenericParameterTypes();
  this.parameterAnnotationsArray = method.getParameterAnnotations();

Builder创建完了,我看一下build()做了什么?
点进去,有点恶心 ,东西太多了。一大堆初始化

public ServiceMethod build() {
  callAdapter = createCallAdapter();
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  if (!hasBody) {
    if (isMultipart) {
      throw methodError(
          "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
      throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
          + "request body (e.g., @POST).");
    }
  }

  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }

    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }

  if (relativeUrl == null && !gotUrl) {
    throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
  }
  if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
    throw methodError("Non-body HTTP method cannot contain @Body.");
  }
  if (isFormEncoded && !gotField) {
    throw methodError("Form-encoded method must contain at least one @Field.");
  }
  if (isMultipart && !gotPart) {
    throw methodError("Multipart method must contain at least one @Part.");
  }

  return new ServiceMethod<>(this);
}

初始化完了以后,把你的各种初始化信息放到ServiceMethod

  return new ServiceMethod<>(this);

用一个Builder模式创建了一个ServiceMethod,我知道很清楚是一个Builder模式,但是我不知道做了什么事,那么我现在要暂时先放弃一下,先不管他。等会我拐回来看。

ServiceMethod(Builder<R, T> builder) {
  this.callFactory = builder.retrofit.callFactory();
  this.callAdapter = builder.callAdapter;
  this.baseUrl = builder.retrofit.baseUrl();
  this.responseConverter = builder.responseConverter;
  this.httpMethod = builder.httpMethod;
  this.relativeUrl = builder.relativeUrl;
  this.headers = builder.headers;
  this.contentType = builder.contentType;
  this.hasBody = builder.hasBody;
  this.isFormEncoded = builder.isFormEncoded;
  this.isMultipart = builder.isMultipart;
  this.parameterHandlers = builder.parameterHandlers;
}

现在我大概知道ServiceMethod是一个封装了方法信息(注解、返回类型、参数注解…) 后,适配到一个okhttpcall,不是很明白,但是大概知道了一点意思。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

这里简单说一下builder这种模式有什么好处。

builder我们一般怎么用的?

Person person = new Person.Builder()
    .name("xx")
    .gender("male")
    .age(25)
    .builder();

他有什么好处?我现在这个人他的名字,年龄什么的是和其他属性相关的,他们可能互相之间属性是相关的。而且他们都有初始化成本。
什么意思呢?比如:
Person person = new Person();
然后我这个人就在内存里面做了初始化了,比如我是一个图形化程序,然后就把这个人画出来了,画了一个普普通通的人,然后,
person.setName(“qiulong”);
person.gendder(“male”);
这个时候,就出问题了,我的程序里面默认的性别是女,你现在是男了,我现在要把这个女性形象给擦掉。,然后重新做一个男性出来。这个时候我之前做的女性他的性能就浪费了,时间也浪费了,而且我现在又要重新去创建那个男性,接下来又有,
person.age(25);
我的系统里面都是默认24岁的,你这25岁了,完了,再把我这24岁的人给擦掉,然后重新画一个25岁的人。
就是每个参数之间有挂钩,或者有初始化成本,一旦你的对象被生出来了,你再对他改动是有性能成本的。很多时候就没有必要。而builder就可以让你在创建之前什么额外工作都不做,我只是好像在做一个配置清单,最后直接初始化出来,这是builder最重要的好处之一。
另外就是你的属性非常多,初始化起来很麻烦,用builder就可以一行定义下来。

4.粗读OkHttpCall

接下来继续读源码,
说到ServiceMethod,他是读了我api里面的method信息,然后把它转成了一个http的call。但是这个call是什么,怎么转的我不知道。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

那么我再看一下OkHttpCall是什么?构造点进去,
怎么这么简单?就两个参数。这就麻烦了,这个serviceMethod好像是根据方法做了转化,然后这个OkHttpCall他给我又非常简单,就这么一点,就是他把这两个参数存起来了,怎么办?

OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
  this.serviceMethod = serviceMethod;
  this.args = args;
}

看一下OkHttpCall是个什么东西?
首先,他是实现了Call这个接口,

final class OkHttpCall<T> implements Call<T> {...}

记得Call是什么吗?我们在api里面定义的方法返回就是一个Call,retrofit教我们用的就是这个call,他们是一个东西。

public interface GitHubService {
    @GET("users/renwuxian/repos")
    Call<BaseBean> getRepos();
}

那我先看一下OkHttpCall他的enqueue做什么事情,因为最终给用户响应的就是getRepos返回的Call的enqueue()。

api.getRepos().enqueue(new Callback<BaseBean>() {
    @Override
    public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {
        System.out.println("success!"+gson.toJson(response.body()));
    }

    @Override
    public void onFailure(Call<BaseBean> call, Throwable t) {

    }
});

这么一大堆,暂时先不看了。总之这个东西好像有点接近我的最终答案了,他们连上了。
我在api定义的方法里面本来就要返回call对象,然后我用动态代理方法生成了一个动态对象,然后他的invoke方法终于给我一个call了。

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

5.粗读adapt

可是这又懵了,这啥意思啊?adapter?不让我直接用?怎么办?看呗,反正前两行都看完了。
第一行,我猜测是对方法的解析。
第二行,我猜测是那个最终的call。
但是到第三行我又不确定第二行是不是我猜测的东西了。但是我觉得前两行基本确定,因为第一行的东西还传给第二行作为参数了。那么我再确认一下我的猜测。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

看完adapter,我就可以决定我这三行应该从哪来细看了。

T adapt(Call<R> call) {
  return callAdapter.adapt(call);
}

我又开始烦了,又有个新东西出现了,叫做callAdapter,我先不管这个callAdapter是什么,先看这个adpter做了什么事情,点进去

T adapt(Call<R> call);

6.决定细读代码的顺序

又是个接口,那怎么办?这三行我都看不懂,先不管他,起码前两行跟我心中的那个结构是特别像的。我觉得你的代码能有多神奇呀?你不就是解析我的代码,然后生成一个call吗?这个看起来就特别像啊,第一行做解析,第二行做生成。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

现在,这么三行的结构,我有两行有点清楚了,那么把这两行看完,我再看一下第三行,这就是我决定读代码的顺序了。

7.细读第一行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;
}

cash部分已经看过了,Builder我也看过了,我现在要看一下build()。
很多时候,读到这,就比较痛苦了,他的大结构我已经知道了,就是Proxy.newProxyInstance(1,2,3),然后最终到这么三行。

public ServiceMethod build() {
  callAdapter = createCallAdapter();
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  if (!hasBody) {
    if (isMultipart) {
      throw methodError(
          "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
      throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
          + "request body (e.g., @POST).");
    }
  }

  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }

    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }

  if (relativeUrl == null && !gotUrl) {
    throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
  }
  if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
    throw methodError("Non-body HTTP method cannot contain @Body.");
  }
  if (isFormEncoded && !gotField) {
    throw methodError("Form-encoded method must contain at least one @Field.");
  }
  if (isMultipart && !gotPart) {
    throw methodError("Multipart method must contain at least one @Part.");
  }

  return new ServiceMethod<>(this);
}

看第一行

callAdapter = createCallAdapter();

callAdapter?这不是刚刚那玩意吗?大致看一下createCallAdapter()

private CallAdapter<T, R> createCallAdapter() {
  Type returnType = method.getGenericReturnType();
  if (Utils.hasUnresolvableType(returnType)) {
    throw methodError(
        "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  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);
  }
}

上面是验证的,核心代码

retrofit.callAdapter(returnType, annotations)

retrofit的calladapter方法被调过来传给我的ServiceMethod,那这个calladapter又是什么?

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}

链过去,代码有点长

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;
    }
  }

  StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
      .append(returnType)
      .append(".\n");
  if (skipPast != null) {
    builder.append("  Skipped:");
    for (int i = 0; i < start; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    builder.append('\n');
  }
  builder.append("  Tried:");
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
  }
  throw new IllegalArgumentException(builder.toString());
}

关键点是这

CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);

现在回顾一下我要做什么,我刚刚看见一个calladapter,我要看他是怎么创建的。前面的代码都可以忘了,我要看calladapter是什么东西,看一下callAdapterFactorys,看一下哪个地方对他进行了修改。

final List<CallAdapter.Factory> callAdapterFactories;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
    List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
    @Nullable Executor callbackExecutor, boolean validateEagerly) {
  this.callFactory = callFactory;
  this.baseUrl = baseUrl;
  this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
  this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
  this.callbackExecutor = callbackExecutor;
  this.validateEagerly = validateEagerly;
}

再看看哪调用了Retrofit(),点击Retrofit()。

return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
    unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);

然后到这个地方,这个callAdapterFactories实际是在哪生成的呢?在上面一点点

List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

有两行,第一行他会把callAdapterFactories填进来,但是是空的。
第二行他会加一个对象,调这个defaultCallAdapterFactory(),点进来

CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
  if (callbackExecutor != null) {
    return new ExecutorCallAdapterFactory(callbackExecutor);
  }
  return DefaultCallAdapterFactory.INSTANCE;
}

ExecutorCallAdapterFactory()再点进来

final Executor callbackExecutor;

ExecutorCallAdapterFactory(Executor callbackExecutor) {
  this.callbackExecutor = callbackExecutor;
}

看谁调用了callbackExecutor

return new ExecutorCallbackCall<>(callbackExecutor, call);

ExecutorCallbackCall点进去

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
  this.callbackExecutor = callbackExecutor;
  this.delegate = delegate;
}

看谁调用了callbackExecutor

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

最终走到这个地方,路上的都可以忘掉。
记不记得前面也有一个onResponse和onFailure,最终链到这,也有一个onResponse和onFailure,他是把我的回调做了一个代理,他让callbackExecutor.execute去处理这个请求的成功和失败。

api.getRepos().enqueue(new Callback<BaseBean>() {
    @Override
    public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {
        System.out.println("success!"+gson.toJson(response.body()));
    }

    @Override
    public void onFailure(Call<BaseBean> call, Throwable t) {

    }
});

execute是什么?他是做线程处理的东西,他可以去切线程。那么execute怎么切线程,他切线程有什么用处呢?
看前面,我当时传过来的是callbackExecutor,我需要知道这个callbackExecutor做了什么,现在我知道我点过去,callbackExecutor做的是转嫁工作,他做的是一个代理工作,做的是一个委托工作,他让我最终返回的结果不管是成功还是失败,我需要转接一下。

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

为什么转接?看一下callbackExecutor他做了什么,

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

他是空的,但是不害怕,我们刚才时候了Platform是android和java8通用的东西,我们看一下android有没有对应的实现。有没有对应的重写?

@Nullable Executor defaultCallbackExecutor() {
  return null;
}

有,在底部,他叫MainThreadExecutor(),这是主线程Executor。
同样的,我看一下他的execute()做了什么,这个execute()做了事情的代理。他的代理交给handler了。到这可能中间可能有点晕,确实我自己看的时候也晕。这里是什么?他把你的网络请求给切到前台了。怎么做到的?就是这个execute()里面。
okhttp他是那么做的,你在哪个线程做,我可以把他放到后台去,retrofit做的就是把你所有的后台做到任务结果拿到前台来,帮你拿到主线程,这个就是callbackExecutor的工作。而这个callbackExecutor最终交给的callAdapterFactory,callAdapterFactory是工厂,创建的一个个callAdapter。他为不同的自定义api(GitHubService里)接口创建callAdapter ,每一个方法对应一个Call,每一个Call对应一个callAdapter。这个calladapter做了什么事情?线程切换。

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

刚才读到第三行代码,我不知道adapter是做了什么事情,

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

我只知道他用了callAdapter.adapt()。 现在读到这,我本来想读ServiceMethod,但是不小心,我知道了callAdapter是干什么的了,他就是一个代理,帮我切一下线程。帮我把内容推到主线程去。那么好,我的一块石头落地了。

T adapt(Call<R> call) {
  return callAdapter.adapt(call);
}

我给你们带的是有一点加速的,有点快的,有一些东西这一行代码与另一行代码之间怎么嵌套关系的,我是没有很详细地讲的。所以我的过程你没有听明白非常正常,但是他的作用,你要很清楚。结构明白了,那么中间的东西你要去了解就很容易。这一行就这个作用,但是他不仅仅是切线程的作用。他还可以做别的,他还可以做rxjava的适配。rxjava的适配也是这个地方。

那么我现在继续把前面两行也简单读一下。 都不能详细说,代码还是很复杂的,细节很多,但是结构还是很简单。
刚才看到loadServiceMethod()里的

result = new ServiceMethod.Builder<>(this, method).build();

builder进去,
第一行我们看懂了。

public ServiceMethod build() {
  callAdapter = createCallAdapter();
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  if (!hasBody) {
    if (isMultipart) {
      throw methodError(
          "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
    }
    if (isFormEncoded) {
      throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
          + "request body (e.g., @POST).");
    }
  }

  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }

    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }

  if (relativeUrl == null && !gotUrl) {
    throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
  }
  if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
    throw methodError("Non-body HTTP method cannot contain @Body.");
  }
  if (isFormEncoded && !gotField) {
    throw methodError("Form-encoded method must contain at least one @Field.");
  }
  if (isMultipart && !gotPart) {
    throw methodError("Multipart method must contain at least one @Part.");
  }

  return new ServiceMethod<>(this);
}

第二行就是 responseType,你的api接口返回值类型。

 responseType = callAdapter.responseType();

接下来都是结构简单,细节复杂的东西。
比如createResponseConverter() ,什么叫responseConverter?retrofit的底层是okhttp,我们可以得到的是什么?我们可以得到一个具体对象(besn)。我们得到的并不是一个ResponseBody,怎么做的?做的转换。怎么转换的,就是用的Converter。

responseConverter = createResponseConverter();

responseConverter点过去简单说一下,

Converter<ResponseBody, T> responseConverter;

在retrofit里面,他有Converter这个东西,Converter他做什么转换,Converter除了做返回结果他会给你转换成具体的对象,
还有你请求的东西,有的时候你传入一个Integer,你需要转化成String才能去做网络数据的拼接,你们这个Converter就这么做的。
还有有时候你要传一个图片,你传的是一个File,你怎么把File转换成一个RequestBody,也是靠的Converter
Converter对你的请求和响应都会有转换作用。这是Converter的作用。

接下来

 parseMethodAnnotation(annotation);

parseMethodAnnotation,他是对你的方法去进行解读,对方法的每一个注解去进行解读。怎么解读的?简单看一下,我点进去就能够明白是做什么事情了,虽然我看不懂。

private void parseMethodAnnotation(Annotation annotation) {
  if (annotation instanceof DELETE) {
    parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
  } else if (annotation instanceof GET) {
    parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
  } else if (annotation instanceof HEAD) {
    parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
    if (!Void.class.equals(responseType)) {
      throw methodError("HEAD method must use Void as response type.");
    }
  } else if (annotation instanceof PATCH) {
    parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
  } else if (annotation instanceof POST) {
    parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
  } else if (annotation instanceof PUT) {
    parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
  } else if (annotation instanceof OPTIONS) {
    parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
  } else if (annotation instanceof HTTP) {
    HTTP http = (HTTP) annotation;
    parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
  } else if (annotation instanceof retrofit2.http.Headers) {
    String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
    if (headersToParse.length == 0) {
      throw methodError("@Headers annotation is empty.");
    }
    headers = parseHeaders(headersToParse);
  } else if (annotation instanceof Multipart) {
    if (isFormEncoded) {
      throw methodError("Only one encoding annotation is allowed.");
    }
    isMultipart = true;
  } else if (annotation instanceof FormUrlEncoded) {
    if (isMultipart) {
      throw methodError("Only one encoding annotation is allowed.");
    }
    isFormEncoded = true;
  }
}

对每一个注解有不同的解读。比如我随便点一个GET

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
  if (this.httpMethod != null) {
    throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
        this.httpMethod, httpMethod);
  }
  this.httpMethod = httpMethod;
  this.hasBody = hasBody;

  if (value.isEmpty()) {
    return;
  }

  // Get the relative URL path and existing query string, if present.
  int question = value.indexOf('?');
  if (question != -1 && question < value.length() - 1) {
    // Ensure the query string does not have any named parameters.
    String queryParams = value.substring(question + 1);
    Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
    if (queryParamMatcher.find()) {
      throw methodError("URL query string \"%s\" must not have replace block. "
          + "For dynamic query parameters use @Query.", queryParams);
    }
  }

  this.relativeUrl = value;
  this.relativeUrlParamNames = parsePathParameters(value);
}

回到builder(),上面是对方法的注解的解读, 接下来,

parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
  Type parameterType = parameterTypes[p];
  if (Utils.hasUnresolvableType(parameterType)) {
    throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
        parameterType);
  }

  Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
  if (parameterAnnotations == null) {
    throw parameterError(p, "No Retrofit annotation found.");
  }

  parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}

ParameterHandler,他会去解读你的每一个参数,
找个例子parseParameter,

private ParameterHandler<?> parseParameter(
    int p, Type parameterType, Annotation[] annotations) {
  ParameterHandler<?> result = null;
  for (Annotation annotation : annotations) {
    ParameterHandler<?> annotationAction = parseParameterAnnotation(
        p, parameterType, annotations, annotation);

    if (annotationAction == null) {
      continue;
    }

    if (result != null) {
      throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
    }

    result = annotationAction;
  }

  if (result == null) {
    throw parameterError(p, "No Retrofit annotation found.");
  }

  return result;
}

parseParameterAnnotation是关键,也是解读一大堆注解
对你的每一个参数类型的每一个注解进行解读,比如Url、Path

private ParameterHandler<?> parseParameterAnnotation(
    int p, Type type, Annotation[] annotations, Annotation annotation) {
  if (annotation instanceof Url) {
    if (gotUrl) {
      throw parameterError(p, "Multiple @Url method annotations found.");
    }
    if (gotPath) {
      throw parameterError(p, "@Path parameters may not be used with @Url.");
    }
    if (gotQuery) {
      throw parameterError(p, "A @Url parameter must not come after a @Query");
    }
    if (relativeUrl != null) {
      throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod);
    }
    ...

对方法的解读过程中,他会去判断你这个方法用得对不对。
比如你是一个get,但同时你又往里面加了body,那么我给你报错,get是取东西的,他的body里面不加东西,如果你加了我给你报错。
到这个地方,可以看出来,retrofit除了比okhttp更好用之外,他还会对你的http规范使用有更多的要求,相应的也能让你更方便地去用这个东西。

这些解读过程,你都可以暂时不知道,只需要知道ServiceMethod的build过程,就是把你的方法给解析出来,去读这个方法他具体的配置,读他的返回值,读他的每一个参数,把他们读完以后,解析一下,存下来,等到真正创建call的时候用到。

8.细读enqueue()

到现在,已经证实第一行就是解读method,第二行是把ServiceMethod作为参数填进okhttpcall,第三行是做线程切换,这三行都解读完了,但是我其实还有疑问,就是我之前我读不动的地方。enqueue。

ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(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) {
        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();
      }
    }
  });
}

这一部分只有两个关键

call = rawCall = createRawCall();

我们的call是一个retrofit的call,他是一个外面的包装,真正进行网络请求的是okhttp,那么这个地方就生成了okhttp的call,这是第一个关键,第二个关键就是

 call.enqueue(new okhttp3.Callback() {...}

看着一段是不是觉得有点奇怪,你不是在外面enqueue了一下,怎么里面又enqueue?为什么?因为这个call已经不是retrofit的call了,而是okhttp的call,他掉这个enqueue方法,然后做网络请求,做完之后,就把(okhttp3.Response )rawResponse解析了,解读完之后交给回调,这个callback也许是用户给你的,也许是calladapter(有可能去做线程切换)

解析的东西大致看一下parseResponse()
大致看一下就能感受okhttp和retrofit他们的关系了,
code小于200大于300的报错,因为只有2xx才是正常,这之外的都会报错,但是301、302这些他们都会做自动跳转,这个是okhttp他会做,但是retrofit他不管这些,我这返回这个了我就报一个错。一般到不了retrofit,okhttp就会把这个事做了。
然后204、205我会给你返回一个空对象。
他做这些东西会在okhttp之外做一些额外的干涉,他让我们用得更舒服,但是会有一些限制。

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();

  // Remove the body's source (the only stateful object) so we can pass the response along.
  rawResponse = rawResponse.newBuilder()
      .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
      .build();

  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
    try {
      // Buffer the entire body to avoid future I/O.
      ResponseBody bufferedBody = Utils.buffer(rawBody);
      return Response.error(bufferedBody, rawResponse);
    } finally {
      rawBody.close();
    }
  }

  if (code == 204 || code == 205) {
    rawBody.close();
    return Response.success(null, rawResponse);
  }

  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
  try {
    T body = serviceMethod.toResponse(catchingBody);
    return Response.success(body, rawResponse);
  } catch (RuntimeException e) {
    // If the underlying source threw an exception, propagate that rather than indicating it was
    // a runtime exception.
    catchingBody.throwIfCaught();
    throw e;
  }
}

他是会做parse(解析)的

T body = serviceMethod.toResponse(catchingBody);

点进去

R toResponse(ResponseBody body) throws IOException {
  return responseConverter.convert(body);
}

你给我一个okhttp的ResponseBody,我帮你把他转成你的方法所要返回的参数所要的类型。

OkHttpCall的enqueue做了什么?
第一,创建了okhttp的call,
然后,用它去做后台的请求,
请求完之后,解析body,另外状态码不对的话我也会直接报错,
解析完,交给callback,这个callback可能是一个calladapter(切换线程),也可能直接返回给用户

最后只剩一点点,createRawCall()是怎么创建okhttp的call的?

private okhttp3.Call createRawCall() throws IOException {
  okhttp3.Call call = serviceMethod.toCall(args);
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

又是serviceMethod.toCall(),他刚刚是用toResponse()转换的响应的结果的。这也是用toCall来转换一个call
serviceMethod是之前解析api里面接口后的半成品信息,然后用这些半成品转化成一个真正的call。 这个具体不用看了,他就是跟okhttp的一个交互。

okhttp3.Call toCall(@Nullable Object... args) throws IOException {
  RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
      contentType, hasBody, isFormEncoded, isMultipart);

  @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
  ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

  int argumentCount = args != null ? args.length : 0;
  if (argumentCount != handlers.length) {
    throw new IllegalArgumentException("Argument count (" + argumentCount
        + ") doesn't match expected count (" + handlers.length + ")");
  }

  for (int p = 0; p < argumentCount; p++) {
    handlers[p].apply(requestBuilder, args[p]);
  }

  return callFactory.newCall(requestBuilder.build());
}

到这,retrofit的大致源码就看完了。结构很简单。

4.adapter怎么用到rxjava呢?

添加依赖

implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'

添加addCallAdapterFactory()
为什么叫CallAdapterFactory,因为他是用来创建CallAdapter的,而且CallAdapter是可以转换线程,自动切换到主线程的东西,也可以是rxjava的Observable、Single

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

定义api接口的时候我可以用Call,也可以用Observable,他可以适配多个adapter

@GET("users/renwuxian/repos")
Call<BaseBean> getRepos();
@GET("users/renwuxian/repos")
Observable<BaseBean> getRepos1();

retrofit里面的是callAdapterFactories,他是一个工厂集合,不是一个工厂。

final List<CallAdapter.Factory> callAdapterFactories;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
com.squareup.okhttp2是一个开放源代码的网络请求库,用于处理HTTP和HTTPS请求。它是Square公司开发的,并且提供了许多功能和灵活性来简化网络请求的处理。 OkHttp是一个多功能的库,支持与服务器的各种通信和交互。它支持GET、POST、PUT、DELETE等HTTP方法,并且可以发送和接收各种类型的数据,包括JSON、XML、图片等。它还提供了处理文件上传和下载的功能。 这个库具有高度可定制性,可以根据不同的需求进行配置。可以设置超时时间、缓存策略、重试策略等。它还支持添加自定义的拦截器来处理请求和响应,可以对请求进行修改或者添加自定义的头部信息。 OkHttp2支持异步请求和同步请求。异步请求使用回调机制,可以通过设置回调方法来处理服务器的响应。同步请求将会阻塞调用线程,直到服务器返回响应。 该库具有高性能和高效率。它使用连接池来复用连接,减少了连接的建立和关闭的时间。它还支持Gzip压缩和缓存等机制,可以减少带宽的使用。 OkHttp2还提供了一些额外的功能,如取消请求、重定向、Cookie管理等。它还支持HTTPS的安全连接,提供了验证证书的机制,可以保证通信的安全性。 总之,com.squareup.okhttp2是一个功能强大、易于使用的网络请求库。无论是开发Android应用程序还是服务端程序,它都是一个不错的选择。它具有丰富的功能和高度的定制性,同时也是一个性能优秀和稳定可靠的库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值