美文网首页
Retrofit源码解析

Retrofit源码解析

作者: houtrry | 来源:发表于2020-08-24 14:25 被阅读0次

    写在前面

    retrofit源码版本2.4.0
    前置知识: Java动态代理

    从用法开始

    代码来自https://www.jianshu.com/p/021a2c6e128b

    public interface RetrofitService {
    
        /**
         * 获取快递信息
         * Rx方式
         *
         * @param type   快递类型
         * @param postid 快递单号
         * @return Observable<PostInfo>
         */
        @GET("query")
        Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
    }
    
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://www.kuaidi100.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
            .build();
    RetrofitService service = retrofit.create(RetrofitService.class);
    Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");
    observable.subscribeOn(Schedulers.io()) 
            .observeOn(AndroidSchedulers.mainThread()) 
            .subscribe(new Observer<PostInfo>() { 
    
                @Override
                public void onCompleted() {
    
                }
    
                @Override
                public void onError(Throwable e) {
    
                }
    
                @Override
                public void onNext(PostInfo postInfo) {
                    Log.i("http返回:", postInfo.toString() + "");
                }
            });
    

    问题有三个:

    • 为什么只是写接口Service就可以实现网络请求, 这个逻辑是怎样的?
    • 返回对象是怎么转成Observable的?
    • 返回对象ResponseBody怎么通过Gson转成泛型对象的?

    源码梳理

    Retrofit

    Retrofit#create

      public <T> T create(final Class<T> service) {
        //检查service是否是接口类型, 并且service不允许继承其它接口
        Utils.validateServiceInterface(service);
          //是否提前加载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) {
                  //如果调用的是Object中的方法, 则直接调用该方法
                  return method.invoke(this, args);
                }
                //是否是平台的默认方法
               //Platform是接口, 有Android和Java8两个实现类
                //上面的Platform.get()方法会判断当前的系统类型
                //之所以这么处理, 是因为像Java8那样, 接口中是支持默认方法的
                //如果是默认方法, 就直接调用
                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);
                //生成OkHttpCall并调用执行
                return serviceMethod.adapt(okHttpCall);
              }
            });
      }
    

    这里重点就是最后的三行方法.

    Retrofit#loadServiceMethod

      //动态代理前面执行的这个方法
      //遍历service中的全部public方法执行loadServiceMethod
      private void eagerlyValidateMethods(Class<?> service) {
        Platform platform = Platform.get();
        for (Method method : service.getDeclaredMethods()) {
          if (!platform.isDefaultMethod(method)) {
            loadServiceMethod(method);
          }
        }
      }
    
    //serviceMethodCache缓存信息
      ServiceMethod<?, ?> loadServiceMethod(Method method) {
    //serviceMethodCache的类型是Map<Method, ServiceMethod<?, ?>>
    //如果已经加载过, 就从serviceMethodCache取出直接返回
    //这也就是执行eagerlyValidateMethods的意义
    //提前加载
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;
    
    //保证线程按全
    //这里是不是很像单例里的双检锁/双重校验锁(DCL)
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            //如果没加载过, 就创建ServiceMethod
            //ServiceMethod这里就是保存方法的各个信息
            result = new ServiceMethod.Builder<>(this, method).build();
            //缓存进serviceMethodCache
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    

    ServiceMethod

    ServiceMethod.Builder<>(this, method).build()

        Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          //获取方法的注解信息, 注解可以有多个, 所以是数组
          //比如注解@Get @NotNull
          this.methodAnnotations = method.getAnnotations();
          //方法的参数类型
          this.parameterTypes = method.getGenericParameterTypes();
         //方法的参数中的注解
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    
        public ServiceMethod build() {
          //获取callAdapter 
          //注意这个方法, 该方法和问题2有关
          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?");
          }
          //注意这个方法, 该方法和问题3有关
          responseConverter = createResponseConverter();
    
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          //...各种检查
    
          //Builder模式
          //最终生成ServiceMethod, 将builder中的各个参数保存到ServiceMethod中
          return new ServiceMethod<>(this);
        }
    
    

    看到这里我们大概可以看出, 接口Service中的方法信息被一一对应保存在了对应的ServiceMethod中.

    ServiceMethod#adapt

    现在回到Retrofit#create方法的最后, 我们调用了如下方法

                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                //这里尤其要注意的是, adapt的参数是Call的实现类, OkHttpCall, 后面还要用到
                return serviceMethod.adapt(okHttpCall);
    

    下面我们就来看看 ServiceMethod#adapt

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

    ServiceMethod#adapt方法很简单, 就是调用了CallAdapter#adapt, 而CallAdapter是接口, 这个时候我们就需要来看看这个callAdapter到底是谁了

    在ServiceMethod.Builder#build方法中, 我们创建了callAdapter

          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
            //最终, 我们的callAdapter是在retrofit类中获取
            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

      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;
        //遍历callAdapterFactories, 一个一个去找
        //找到就返回
        for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
          CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
       //...
        //如果没找到, 输出异常信息
      }
    
    

    如果我们看一下callAdapterFactories, 就会发现, 这个Map里的值正是我们在创建Retrofit的时候通过retrofit2.Retrofit.Builder#addCallAdapterFactory方法传进去的RxJavaCallAdapterFactory.create(), 该方法创建了RxJavaCallAdapterFactory, 也就是说, 通过retrofit2.adapter.rxjava.RxJavaCallAdapterFactory#get方法, 我们获取到了真正的CallAdapter

    RxJavaCallAdapterFactory#get

      @Override
      public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        Class<?> rawType = getRawType(returnType);
        boolean isSingle = rawType == Single.class;
        boolean isCompletable = rawType == Completable.class;
        //如果方法的返回值类型不是Observable, 也不是Single和Completable
        //就返回空
        //也就是不由RxJavaCallAdapter处理
        if (rawType != Observable.class && !isSingle && !isCompletable) {
          return null;
        }
    
        //最后, 返回的是RxJavaCallAdapter
        if (isCompletable) {
          return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
        }
    
        //...
    
        return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
            false);
      }
    

    也即是, 真正的CallAdapter其实是RxJavaCallAdapter

    RxJavaCallAdapter#adapt

    现在我们重新回头来看retrofit2.ServiceMethod#adapt

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

    我们知道了这里callAdapter是RxJavaCallAdapter, 参数call是OkHttpCall
    所以我们来看RxJavaCallAdapter#adapt

      //注意, 这里, 也是问题2的关键
      @Override public Object adapt(Call<R> call) {
        //如果是异步方法, 就返回CallEnqueueOnSubscribe, 如果是同步, 就返回CallExecuteOnSubscribe
        OnSubscribe<Response<R>> callFunc = isAsync
            ? new CallEnqueueOnSubscribe<>(call)
            : new CallExecuteOnSubscribe<>(call);
    
        OnSubscribe<?> func;
        if (isResult) {
          func = new ResultOnSubscribe<>(callFunc);
        } else if (isBody) {
          func = new BodyOnSubscribe<>(callFunc);
        } else {
          func = callFunc;
        }
        Observable<?> observable = Observable.create(func);
    
        if (scheduler != null) {
          observable = observable.subscribeOn(scheduler);
        }
    
        if (isSingle) {
          return observable.toSingle();
        }
        if (isCompletable) {
          return observable.toCompletable();
        }
        return observable;
      }
    
    final class CallEnqueueOnSubscribe<T> implements OnSubscribe<Response<T>> {
      private final Call<T> originalCall;
    
      CallEnqueueOnSubscribe(Call<T> originalCall) {
        this.originalCall = originalCall;
      }
    
      @Override public void call(Subscriber<? super Response<T>> subscriber) {
        // Since Call is a one-shot type, clone it for each new subscriber.
        Call<T> call = originalCall.clone();
        final CallArbiter<T> arbiter = new CallArbiter<>(call, subscriber);
        subscriber.add(arbiter);
        subscriber.setProducer(arbiter);
        //这里, 执行了OkHttpCall#enqueue, 拿到返回值后, 通过arbiter发射出去
        call.enqueue(new Callback<T>() {
          @Override public void onResponse(Call<T> call, Response<T> response) {
            arbiter.emitResponse(response);
          }
    
          @Override public void onFailure(Call<T> call, Throwable t) {
            Exceptions.throwIfFatal(t);
            arbiter.emitError(t);
          }
        });
      }
    }
    

    以异步为例, 如果简单些, 可以如下

            Observable.create(new Observable.OnSubscribe<T>() {
                @Override
                public void call(Subscriber<T> subscriber) {
                    call.enqueue(new Callback() {
                        @Override
                        public void onResponse(Call call, Response response) {
                            subscriber.onNext(response);
                        }
    
                        @Override
                        public void onFailure(Call call, Throwable t) {
                            subscriber.onError(t);
                        }
                    });
                }
            });
    

    到这里, 我们就可以回答问题2了.
    Retrofit通过动态代理实现了接口中的方法, 在方法的最后, 使用了RxJavaCallAdapter#adapt方法来获取结果, 而RxJavaCallAdapter#adapt做的也就是通过Observable.create创建Observable, 在调用OkHttpCall#enqueue方法拿到返回的结果后, 通过Observable发射出去, 生成Observable的数据流. 这样就把生成的结果转成了Observable.

    在上面的异步方法中, 我们实际上通过retrofit2.Call#enqueue来获取请求结果, 而这里的Call, 实际上是OkHttpCall, 所以, 我们来看下OkHttpCall#enqueue

    OkHttpCall

    OkHttpCall中有OkHttpCall#enqueue和OkHttpCall#execute, 分别对应异步方法和同步方法
    我们这里只说OkHttpCall#enqueue

    OkHttpCall#enqueue

        //如果callback为空, 抛出异常
        checkNotNull(callback, "callback == null");
        //...检查各个参数
        //这里, 才是真正的调用了Okhttp的enqueue方法
        //调用OkHttp的enqueue异步方法, 获取结果
        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();
            }
          }
        });
    
      Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        //...
         //解析返回结果
        //这里也是问题3的关键
        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
            //解析结果
            //泛型解析
            //这里跟我们创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)对应
           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;
        }
      }
    

    所以, 问题3就是, 在OkHttpCall中, 拿到返回结果后, 将结果交给创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)生成的对应的GsonConvert, 转成对应的对象

    重新梳理

    这里, 我们回国头来重新看

     public <T> T create(final Class<T> service) {
        //...
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
            new InvocationHandler() {
    
              @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                //...
    
                ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.adapt(okHttpCall);
              }
            });
      }
    
    1. 首先通过动态代理, 生成对应接口的实现类. 调用接口中的方法时, 执行动态代理的invoke方法
    2. ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
      方法, 获取接口中方法的信息(方法返回值类型/注解信息/参数类型/参数注解等)
    3. 创建OkHttpCall(封装Okttp中的Call为OkHttpCall)
    4. 执行CallAdapter#adapter(这里的CallAdapter实际为RxJavaCallAdapter), 在RxJavaCallAdapter#adapter中执行OkHttpCall#enqueue(以异步为例)执行网络请求, 并用Observable将结果发射出去成为Observable

    相关文章

      网友评论

          本文标题:Retrofit源码解析

          本文链接:https://www.haomeiwen.com/subject/uuogjktx.html