Android技能树 — 网络小结(7)之 Retrofit源码详细解析

前言:

哈哈,其实写的仍是很水,各位原谅我O(∩_∩)O。html

介于本身的网络方面知识烂的一塌糊涂,因此准备写相关网络的文章,可是考虑所有写在一篇太长了,因此分开写,但愿你们能仔细看,最好能够指出个人错误,让我也能纠正。java

1.讲解相关的整个网络体系结构:web

Android技能树 — 网络小结(1)之网络体系结构面试

2.讲解相关网络的重要知识点,好比不少人都听过相关网络方面的名词,可是仅限于听过而已,什么tcp ,udp ,socket ,websocket, http ,https ,而后webservice是啥,跟websocket很像,socket和websocket啥关系长的也很像,session,token,cookie又是啥。json

Android技能树 — 网络小结(2)之TCP/UDP设计模式

Android技能树 — 网络小结(3)之HTTP/HTTPSapi

Android技能树 — 网络小结(4)之socket/websocket/webservice数组

相关网络知识点小结- cookie/session/token(待写)缓存

3.相关的第三方框架的源码解析,毕竟如今面试个大点的公司,okhttp和retrofit源码是必问的。bash

Android技能树 — 网络小结(6)之 OkHttp超超超超超超超详细解析

Android技能树 — 网络小结(7)之 Retrofit源码详细解析


正文

由于我平时使用的都是Rxjava2 + Retrofit ,因此我相关的源码解析都是配合RxJava来的,而不是Call返回对象。

读本文的我推荐你们最好对OKHttp源码有所了解,再来看本文,由于Retrofit内部仍是经过OkHttp发出网络请求。你们也能够看我前面写的:Android技能树 — 网络小结之 OkHttp超超超超超超超详细解析, 同时本文不会再去教你们Retrofit的基础使用,若是要看一些简单使用,能够看下面的一些推荐博客:

Android Retrofit 2.0 的详细 使用攻略(含实例讲解)

Android:Retrofit 结合 RxJava的优雅使用(含实例教程)

咱们先上一张别的大佬博客中的一张图:

这个图画的很好,可是这个图更多的是从大局观来看,因此若是对于源码不是有一些基础了解的话,看这个图很容易就忘记。

看过个人Okhttp源码分析的文章:Android技能树 — 网络小结之 OkHttp超超超超超超超详细解析,咱们文中的Okhttp流程图就是跟着源码一步步来画的。我更喜欢是跟着源码一步步来画流程图(PS:实际上是我水平太差了,没法一会儿总结处第三方库的各类设计模式的使用),因此Retrofit我也画了下面这个图:

而等会咱们分析完这个跟着源码分析的流程图后,再回头看上面的别人博客中的总结的Retrofit结构图,就会很简单了。

首先咱们来肯定整体大纲:

咱们知道咱们的目标是要发起一次网络请求,他有这么几步:

  1. 告诉它一些基本信息,好比url地址,网络请求方式(get、post、...等),请求参数值。而后拼装成一个标准的网络Request请求的格式发出去。因此这里有二步动做:1.先解析咱们写的参数,2.再解析完后拼装成标准的网络Request请求格式
  2. 发出请求后,接收到了后台的Response返回结果,咱们要把Resonse转换成咱们想要的返回结果。可是咱们写的想要的返回结果又有二大关键地方,咱们日常的返回结果多是X <Y>,咱们先来看外面的X的类型,好比咱们常见的返回结果是Call<Y> 和 Observable<Y>,因此咱们在转换的时候一是要考虑最外面的那个返回类型的转换。另一个是Y的类型,也就是里面咱们具体写的Bean对象,好比咱们直接返回字符串,那可能就是Observable<String>,又或者是本身定义的xxxBean对象,那就是Observable<xxxBean>因此咱们要有二类转换:1.外层的结果类型,好比Call或者Observable等,2.是泛型里面填的具体的Bean对象类型

因此咱们总结起来就须要四步:

  1. 解析并拿到咱们写的一些参数(url,请求方式(post/get),请求参数......)
  2. 根据咱们写的参数,拼成一个网络请求Request,去帮咱们发起请求。
  3. Response如何转换成Call或者Observable等返回类型,和第4步中的Bean对象拼成了Call《Bean》或者Observable《Bean》
  4. Response如何转换成咱们所须要的具体的Bean对象。

没错,下次别人问你,你就内心有数了,到底Retrofit作了什么内容,你就跟别人说很简单啦,大体作了上面四步,逼格一会儿提升了。。


1. 建立Retrofit对象

我这里直接先把建立Retrofit的对象的代码写上:

Retrofit retrofit = new Retrofit.Builder()
    .client(new OkHttpClient())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl("https://xxxx.com/")
    .build();
复制代码

不要问建立Retrofit的各自的方法是干吗的,咱们后面会一步步讲解。

2. 如何解析并拿到咱们写的参数

咱们知道咱们日常是这样写的:

咱们随便写一个常见的获取某个用户的我的信息接口来讲明:

InfoApi.java:
interface InfoApi{
    @GET("userinfo.do")
    Observable<UserBean> getInfo(@Query("name") String nameStr);
}
复制代码

那咱们要拿到:

  1. path值:上面建立Retrofit时候传入的baseUrl + userinfo.do = "https://xxxx.com/userinfo.do"
  2. 网络请求的方式:GET请求
  3. 发送的参数query :name=nameStr

最终咱们发现是GET请求,因此这么拼在一块儿:path + "?" + query = http://xxxx/userinfo.do?name=nameStr

因此咱们来看如何一步步拿到相关参数:

咱们知道上面写的InfoApi.java是要被retrofit加载进去的:

retrofit.create(InfoApi.class);
复制代码

因此咱们要来看create方法的具体操做前,咱们先来了解一下基础知识,那就是代理模式,若是知道代理模式的,直接能够忽略此处,直接往下看。

2.1 create方法:

在看create代码之间,咱们要先学会代理模式相关知识

原本也想一步步长篇大论的写下,可是后来看到一篇不错的文章,写的挺仔细的:java动态代理实现与原理详细分析 ,但愿你们能仔细看完,在看下面的内容。

咱们点进去查看具体的代码:

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (this.validateEagerly) {
        this.eagerlyValidateMethods(service);
    }

    
    //'使用了代理模式'
    return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
        private final Platform platform = Platform.get();

        public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(this, args);
            } else if (this.platform.isDefaultMethod(method)) {
                return this.platform.invokeDefaultMethod(method, service, proxy, args);
            } else {
                
                //'咱们能够看到咱们写的接口里面的的method传入到了loadServiceMethod方法里面,从而获得了咱们定义在method上面的相关参数信息。'
                ServiceMethod<Object, Object> serviceMethod = Retrofit.this.loadServiceMethod(method);
                
                //'咱们传入的方法的参数args和上面得到的ServiceMethod,一块儿传入OkHttpCall构造函数中,获得OkHttpCall对象'
                OkHttpCall<Object> okHttpCall = new OkHttpCall(serviceMethod, args);
                
                return serviceMethod.adapt(okHttpCall);
            }
        }
    });
}
复制代码

咱们能够看到咱们调用的getInfo这个method方法传入了:

ServiceMethod<Object, Object> serviceMethod = Retrofit.this.loadServiceMethod(method);
复制代码

咱们进去查看:

ServiceMethod<?, ?> loadServiceMethod(Method method) {

//'从缓存中去读'
ServiceMethod<?, ?> result = (ServiceMethod)this.serviceMethodCache.get(method);
    if (result != null) {
        return result;
    } else {
        Map var3 = this.serviceMethodCache;
        synchronized(this.serviceMethodCache) {
            result = (ServiceMethod)this.serviceMethodCache.get(method);
            if (result == null) {
                //'若是缓存中没有,则新建'
                result = (new retrofit2.ServiceMethod.Builder(this, method)).build();
                //'新建完后再放入缓存中'
                this.serviceMethodCache.put(method, result);
            }

            return result;
        }
    }
}
复制代码

咱们能够看到新建的方法:

(new retrofit2.ServiceMethod.Builder(this, method)).build();
复制代码

咱们来看ServiceMethod类下的Builder的构造函数:

Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    //'Java特有的方法,能够获取Java方法上面的注解标识,好比:@POST,@GET'
    this.methodAnnotations = method.getAnnotations();
    //'获取方法参数里面定义的参数类型,好比:String,boolean'
    this.parameterTypes = method.getGenericParameterTypes();
    //'获取方法里面的注解标识,好比:@Query,@Path'
    this.parameterAnnotationsArray = method.getParameterAnnotations();
}
复制代码

是否是一会儿就知道了,原来是经过这样的方式拿到了咱们写在方法上面的一些参数值,若是还不清楚Method的这几个方法,能够看下面的相关连接:
Java获取类、方法、属性上的注解
java.lang.reflect.Method.getGenericParameterTypes()方法示例.
使用反射得到参数列表里的注解getParameterAnnotations.

咱们建立ServiceMethod由于是使用的Builder模式,因此最终要调用build()方法来建立实例:

public ServiceMethod build() {
      //'建立了CallAdapter对象,具体干吗用的,具体后面会讲解'
      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对象,具体后面会讲解'
      responseConverter = createResponseConverter();
    
      //'对于咱们写的接口请求方法的方法上面的注解进行相关判断,'
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      //'由于进行方法上面注解的解析了,因此httpMethod的也就相应的被赋值了, 若是为空,就说明你写的请求接口方法没有写@GET等,就会抛出异常'
      if (httpMethod == null) {
        throw methodError(“HTTP method annotation is required (e.g., @GET, @POST, etc.).”);
      }
      
      //'由于上面解析了,因此好比咱们发现是@GET请求,这时候hasBody会是false,若是你还用了Multipart注解,就会报错了,他要求是要有request body的,@GET请求是不能使用Multipart的'
      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              “Multipart can only be specified on HTTP methods with request body (e.g., @POST).”);
        }
        
        //'同上,表单提交是必定要求有request body的'
        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];
      
      //'遍历咱们获取的方法里面的注解集合,好比@Query,@Path等'
      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.”);
        }
        
        //'而后对咱们写的方法内部参数注解进行判断,看写的是否正确等 这里的判断很长,好比若是你用的是注解@Body,那么先判断你是否用了方法上面的@FormEncode注解或者@Multipart注解, 否则就报错,而后由于咱们填的参数是对象了,因此内部须要经过RequestBodyConverter来进行转换,把咱们传的对象,变成了RequestBody对象。 具体不少不少判断,各类注解的判断我都不一一讲了,你们只要进去看方法详细代码就能够了。'
        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);
}
复制代码

好,咱们已经成功拿到了咱们的方法中的红色框出来的部分,绿色的部分咱们尚未获取。

而代理模式的invoke方法里面的参数 @Nullable Object[] args,就是咱们具体传入的参数,好比我这么写:

getInfo("青蛙要fly");
复制代码

args里面就有了咱们传入的"青蛙要fly"字符串。这样咱们是否是就获取了上面的其中一个绿色框nameStr的内容了。

咱们拿到包含了这些红色框参数的ServiceMethod对象后,加上咱们传入的绿色的框的nameStr的具体的值,咱们已经能够进行网络Request请求的所必要的参数了 (另一个绿色的框只是用来最后网络请求成功后拿到的Response进行转换,因此这时候不知道都不影响Request请求)

咱们能够看到咱们得到到的信息,又用来生成了OkHttpCall对象,而后调用了serviceMethod.adapt(okHttpCall);方法。

那咱们能够看到create接下去已经没有其余代码了,因此serviceMethod.adapt(okHttpCall);确定会帮咱们用刚才拿到的已知参数,帮咱们拼成Request,完成一次网络请求。


3.根据咱们写的参数,拼成Request请求

咱们上面已经说到了进入了serviceMethod.adapt(okHttpCall);方法了,咱们点进去查看:

T adapt(Call<R> call) {
    return callAdapter.adapt(call);
}
复制代码

咱们能够看到是调用了callAdapter类的adapt方法。那这个callAdapter对象又是什么呢?

还记不记得咱们第一大步:建立Retrofit对象时候的代码:

Retrofit retrofit = new Retrofit.Builder()
    .client(new OkHttpClient())
    //'这里传入了CallAdapterFactory,而Factory类是用来建立具体的CallAdapter对象的工厂类'
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl("https://xxxx.com/")
    .build();
复制代码

因此本文中咱们使用的CallAdapter是RxJava2CallAdapterFactory建立的,咱们先来看ServiceMethod里面建立CallAdapter的方法:

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);
    }
    
    //'若是方法的返回结果是void,则抛出异常'
    if (returnType == void.class) {
        throw methodError(“Service methods cannot return void.”);
    }
    
    //'咱们前面提过的,获取方法上的注解,好比@GET等'
    Annotation[] annotations = method.getAnnotations();
    try {
       
       //'拿着咱们的接口请求方法的返回对象及方法上的注解信息,'
       //'去经过Retrofit类的callAdapter类去生成一个CallAdapter对象'
       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方法,咱们不看都知道,经过咱们前面建立Retrofit对象时候传入的addCallAdapterFactory的工厂类来建立具体的CallAdapter,固然咱们具体仍是要具体代码一步步来看过程。

咱们在调用addCallAdapterFactory加入咱们的RxJava2CallAdapterFactory.create(),因此先来看下addCallAdapterFactory方法作了什么:

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
  callAdapterFactories.add(checkNotNull(factory, "factory == null"));
  return this;
}
复制代码

咱们能够简单的看到,就是把咱们的Factory工厂类对象加入到private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();这个List队列中而已。

那这个队列到底都加了哪些工厂类的,若是我在建立Retrofit对象时候不调用addCallAdapterFactory方法,难道这个队列就是空的????那又怎么去生成CallAdapter对象?

首先确定要加入咱们本身传入的Factory,有可能一个,也可能传入多个:

Retrofit retrofit = new Retrofit.Builder()
    ........
    
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addCallAdapterFactory(xxxxxxCallAdapterFactory.create())
    .addCallAdapterFactory(yyyyyyCallAdapterFactory.create())
    ........
    ........
    .build();

复制代码

可是为了防止咱们创建Retrofit对象时候不调用addCallAdapterFactory传入本身的Factory,因此自己这个队列还会加入默认的Factory:

//'看名字就知道,加入平台的默认的CallAdapterFactory(有java8 和 Android Platform,咱们这里确定是Android)'
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
复制代码

固然这个ExecutorCallAdapterFactory确定是继承了CallAdapter.Factory:

咱们已经知道了咱们的CallAdapterFactory队列里面包含了哪些工厂类了。接下来咱们再来具体的Retrofit的callAdapter的方法:

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    //'由于可能有多个CallAdapterFactory工厂类,因此要每一个工厂类都去试一下,有一个成功就直接返回了'
    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;
    
    //'循环遍历全部的CallAdapterFactory,而后哪一个能成功生成CallAdapter,就直接返回'
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    
    //'若是全部的CallAdapterFctory都不能使用,就拼接字符串,抛出异常'
    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());
}
复制代码

有可能有人会问,为何CallAdapterFactory有可能生成CallAdapter不成功??还要一个个去遍历?

由于咱们同时传入了咱们须要返回的对象的类型传入到了CallAdapterFactory中,你说若是你是默认的ExecutorCallAdapterFactory工厂类,你却传入了Rxjava的返回相关参数,好比咱们例子中的Observable<UserBean>,它的代码里面都不认识这种返回类型,怎么帮你去生成对象,并且代码也是加了判断,若是返回类型不是Call类型,直接就退出了。

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //'若是不是Call.class,直接退出生成CallAdapter对象'
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    .......
    .......
}
复制代码

因此咱们来看下RxJava2CallAdapterFactory里面怎么生成相应的CallAdapter的:

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
    
    
    
    //'若是咱们的返回类型是Completable,就直接返回RxJava2CallAdapter对象,里面的responseType是void'
    if (rawType == Completable.class) {
      // Completable is not parameterized (which is what the rest of this method deals with) so it
      // can only be created with a single configuration.
      return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
          false, true);
    }


    //'判断是不是Flowable或者Single或者Maybe'
    boolean isFlowable = rawType == Flowable.class;
    boolean isSingle = rawType == Single.class;
    boolean isMaybe = rawType == Maybe.class;
    //'若是既不是上面三种又不是Observable类型,直接返回null'
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }


    boolean isResult = false;
    boolean isBody = false;
    Type responseType;
    
    //'若是不是泛型类的,好比Observable<XXXX> ,则抛异常'
    if (!(returnType instanceof ParameterizedType)) {
      String name = isFlowable ? "Flowable"
          : isSingle ? "Single"
          : isMaybe ? "Maybe" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }
    
    //'获取泛型中的具体参数,好比Observable<xxxBean>中的xxxBean的type'
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    //'获取xxxBean具体的Class对象'
    Class<?> rawObservableType = getRawType(observableType);
    
    //'判断咱们上面获取的泛型内容(xxxBean)是否是Response'
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      
      //'判断咱们上面获取的泛型内容(xxxBean)是否是Result'
    } else if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else {
    
      //'咱们日常开发泛型里面填的确定是本身的Bean对象 //因此最后走的是这里的代码'
      responseType = observableType;
      //'同时isBody设置为true'
      isBody = true;
    }

    //'生成具体的Rxjava2CallAdapter对象'
    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
}
复制代码

既然咱们CallAdapter对象也创建完了,咱们回到最刚开始的地方,还记得咱们前面分析的代码是到了callAdapter.adapt(okHttpCall)(若是忘记的同窗,能够从新回头看下)

因此咱们如今已经创建的Rxjava2CallAdapter对象了,咱们来看下它的adapt方法:

@Override public Object adapt(Call<R> call) {
    /**
    '不少人会说这个isAsync,是否异步是哪里设置的, 其实就是再咱们传入Factory对象时候创建的。 Retrofit retrofit = new Retrofit.Builder() .client(new OkHttpClient()) 咱们看见建立Factory对象,能够是createAsync()或者create()方法二种来建立,从而决定是同步仍是异步操做 .addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync()) 或者是 .addCallAdapterFactory(RxJava2CallAdapterFactory.create() .build();'
    */
    
     //'咱们能够看到上面根据是否异步,创建不一样的Observable对象,咱们用复杂点的来说解吧, 就当咱们创建的时候使用的是RxJava2CallAdapterFactory.createAsync()方法,因此拿到的对象是CallEnqueueObservable'
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);
   

    //'由于咱们Observable<xxxBean>里面包含的是本身Bean,因此创建的时候isBody = true;'
    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      //'因此咱们的Observable为BodyObservable'
      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();
    }
    
    //'因此最终返回了BodyObservable<CallEnqueueObservable>'
    return observable;
  }
复制代码

BodyObservable看名字就知道是一个自定义Observable:

final class BodyObservable<T> extends Observable<T> {
  private final Observable<Response<T>> upstream;

  BodyObservable(Observable<Response<T>> upstream) {
    this.upstream = upstream;
  }

  @Override protected void subscribeActual(Observer<? super T> observer) {
  
    //'当有Observer注册咱们的Observable的时候, 实际上是咱们前面的传入的CallEnqueueObservable去注册了 一个BodyObserver<咱们本身写的Observer>'
    upstream.subscribe(new BodyObserver<T>(observer));
  }

}
复制代码

因此核心仍是咱们传入的CallEnqueueObservable这个Observable,因此最后仍是要看这个类的源码:

final class CallEnqueueObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall;

  CallEnqueueObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    
    
    Call<T> call = originalCall.clone();
    //'咱们能够看到简历了一个CallCallback对象,传入了用户写的咱们前面建立的OkHttpCall对象和用户写的observer对象'
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    //'而后调用了call的enqueue方法, 由于是OkHttpCall对象,因此咱们直接看OkHttpCall对象的enqueue方法便可'
    call.enqueue(callback);
  }

  private static final class CallCallback<T> implements Disposable, Callback<T> {
   .......
   .......
   .......
  }
}


复制代码

OkHttpCall的enqueue方法:

@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 {
        
          //'建立Okhttp3的Call对象(毕竟最后发起网络请求是Okhttp,也要使用它的Call对象)'
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

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

    if (canceled) {
      call.cancel();
    }
    
    
    //'常规Okhttp的操做,call.enqueue方法发起异步请求,估计你们都看得懂,我就很少介绍了,咱们直接看拿到返回的数据处理'
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
        
          //'咱们这里成功的拿到了Okhttp3.Response对象, 因此使用parseResponse方法将rawResponse对象转换成Retrofit的Response对象'
          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();
        }
      }
    });
  }
复制代码

到这里,咱们已经成功的发送了网络请求,而且拿到了主句

4. 如何将Resonse转换成最终咱们想要的结果对象

咱们上面能够看到咱们是讲OkHttp3.Response对象转换成了Retrofit.Response对象,咱们具体来看下:

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {

    //'把Okhttp3.Response中的body部分取出来'
    ResponseBody rawBody = rawResponse.body();

    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    
    //'咱们就当成功请求回来的,因此code是200'
    
    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 {
    
      //'核心代码: 把body部分,经过toResponse方法,变成咱们写入的泛型(也就是Observable<xxxBean>这个xxxBean对象'
      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;
    }
}
复制代码

因此最终咱们发现又回到了serviceMethod里面了,相关的方法调用都在这里面:

R toResponse(ResponseBody body) throws IOException {
   //'能够看到咱们经过responseConverter转换器来对body部分进行了转换'
   return responseConverter.convert(body);
}
复制代码

这个responseConverter又是怎么来的呢?咱们再回到建立Retrofit对象的地方:

Retrofit retrofit = new Retrofit.Builder()
    .client(new OkHttpClient())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    
    //'看见了ConverterFactory没有,就是这里传入了咱们的转换器对象'
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl("https://xxxx.com/")
    .build();

复制代码

咱们来看下具体的代码:

public final class GsonConverterFactory extends Converter.Factory {
    
    //'能够看到默认内部使用的是GSON来进行转换'
    public static GsonConverterFactory create() {
        return create(new Gson());
    }
    
    public static GsonConverterFactory create(Gson gson) {
        return new GsonConverterFactory(gson);
    }
    
    private final Gson gson;

    private GsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }
    
    //'这个方法从名字就能够看出来,是用用来给ResponseBody转换成咱们要的对象'
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(final Type type, Annotation[] annotations, Retrofit retrofit) {
        Type newType = new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                return new Type[] { type };
            }

            @Override
            public Type getOwnerType() {
                return null;
            }

            @Override
            public Type getRawType() {
                return HttpResult.class;
            }
        };
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(newType));
        
        //'能够看到,用在Response的转换器是叫GsonResponseBodyConverter对象'
        return new GsonResponseBodyConverter<>(adapter);
    }
    
    //'这个名字也能够看出来是把咱们传入的对象转换成RequestBody,从而发起请求'
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
        Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        
        //'能够看到,用在Request的转换器是叫GsonRequestBodyConverter对象'
        return new GsonRequestBodyConverter<>(gson, adapter);
    }
}
复制代码

咱们具体来看看GsonResponseBodyConverter:

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    //'根据传入的ResponseBody获得JsonReader'
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      //'很简单,就是GSON进行相关的JSON解析'
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }
}
复制代码

这里咱们看到了既然解析部分是在这里,是否是咱们能够作不少定制化操做,答案固然是Yes,好比我写了个自定义的GsonResponseBodyConverter来进行替换(下面的类就随便写写,你们能够根据本身的需求写本身的自定义转换器):

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, Object> {

    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(TypeAdapter<T> adapter) {
        this.adapter = adapter;
    }

    @Override
    public Object convert(ResponseBody value) throws IOException {
        try {
            //'由于我统一的外层对象都是使用的HttpResult,个人代码是这么写的Observable<HttpResult<xxxBean>>'
            HttpResult apiModel = (HttpResult) adapter.fromJson(value.charStream());
            
            //'直接在这里就对统一处理操做'
            if (apiModel.getCode().equals(CompanyHttpCode.TOKEN_NOT_EXIST)) {
                throw new TokenNotExistException();
            } else if (apiModel.getCode().equals(CompanyHttpCode.TOKEN_INVALID)) {
                throw new TokenInvalidException();
            } else if (!apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE)) {
                // 特定 API 的错误,在相应的 Subscriber 的 onError 的方法中进行处理
                throw new ApiException();
            } else if (apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE) || apiModel.getCode().equals(CompanyHttpCode.SUCCESS_CODE_STR)) {
                return apiModel;
            }

        } finally {
            value.close();
        }
        return null;
    }
}
复制代码

好了,咱们已经拿到了相应的Observable<xxxBean>里面的xxxBean对象了,咱们能够看到:

try {
    //'咱们前面讲过,经过这个方法转换的parseResponse(rawResponse); 把OkHttp3.Response转换成了Retrofit.Response<咱们的bean> '
} catch (Throwable e) {
    callFailure(e);
    return;
}

try {
    //'在转换成功后,咱们就把具体的response从新经过回调函传回去给CallEnqueueObservable'
    callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
    t.printStackTrace();
}
复制代码

CallEnqueueObservable的onResponse方法:

@Override public void onResponse(Call<T> call, Response<T> response) {
      if (disposed) return;

      try {
        
        //'咱们能够看到,Observable调用了observerde的onNext方法把Retrofit.Reponse对象发送了出去'
        observer.onNext(response);
        
        ......
        ......
        ......
}
复制代码

可能有些人就会奇怪了,咱们日常使用,明明拿到的就是具体的里面的xxxBean对象,而不是Response<xxxBean>,那是由于上面咱们提过的,咱们的Observer被BodyObserver包了一层:

private static class BodyObserver<R> implements Observer<Response<R>> {
   
    @Override public void onNext(Response<R> response) {
      if (response.isSuccessful()) {
        
        //'最终到咱们的Observer的时候,就是Response里面包含了的咱们写的xxxBean对象了。'
        observer.onNext(response.body());
      
          
      } else {
        .....
        .....
      }
    }
    
    ......
    ......
  }
复制代码

结语:

因此如今咱们再来看代码,是否是已经就能懂中间到底作了什么操做。哈哈:

interface InfoApi{
    @GET("userinfo.do")
    Observable<UserBean> getInfo(@Query("name") String nameStr);
}

Retrofit retrofit = new Retrofit.Builder()
    .client(new OkHttpClient())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl("https://xxxx.com/")
    .build();


retrofit.create(InfoApi.class)
    .getInfo("青蛙要fly")
    .subscribe(new ResourceObserver<UserBean>() {
        @Override
        public void onNext(UserBean userBean) {
                        
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
});

复制代码

而后再回头看这个图片,是否是也看得懂了:

不知不觉就写完了,哈哈,可能有些地方不详细或者是写的很差又或者是写错了。能够留言,我更但愿的是能指出我哪里写错了,哈哈,这样我也能够纠正错误的知识。

相关文章
相关标签/搜索