Retrofit精髓领悟进阶篇

Retrofit源码解析


简介

在这里插入图片描述
从事移动端开发的人应该都知道Retrofit库,作为一个第三方网络封装库,许多App都会用到它,他提供了注解方式的网络接口定义,自定义请求响应参数转换等等功能,大大提高了开发效率;今天我们尝试着来看看它背后的逻辑好在哪里


Retrofit基本使用

public interface NetApi {
	@POST("test/login")
	LiveData<Response> test(@Body Request request);
}
NetApi api = new Retrofit.Builder()
				.baseUrl(url)
				.addConverterFactory(CustomGsonConverterFactory.create())
				.addCallAdapterFactory(new LiveDataCallAdapterFactory())
				.build().create(NetApi.class);

以上代码就是retrofit的基本使用了

  • 定义网络接口
  • 配置Retrofit参数
  • 反射创建网络接口类

这里大致说一下代码中的关键点:
其一:test方法的POST注解标明这是一个POST方法,Body注解标明request最终要封装到http的请求体中去
其二:Retrofit.Builder需要add两个工厂类,一个convert用于转换http的请求响应参数,另一个CallAdapter调用适配器用于发起网络接口的调用逻辑及相关的操作

注意:相信你也发现了addCallAdapterFactory可以添加不同的调用适配器,这里是LiveData的,或者你曾经还用过RXjava的适配器,而且现在还有Kotlin的协程Coroutine适配器,无论哪种适配器,它都需要完成网络调用的发起工作以及回调工作


源码解读


需求分析

试想,你是Retrofit的设计者,思考一下,它要完成哪些功能?
安全与快捷问题,首先我希望用户能很方便使用库进行开发;其次,网络库中转处理App的诸多数据,不希望别人能直接访问网络中的数据,我希望用户无法修改(至少有一定难度)网络请求响应参数
对象转换问题,app网络请求可能会有不同的对象封装类型,最终都需要转换我这边的统一请求参数对象格式,以及统一响应对象格式,这块我定义好接口转换,让使用者自己去实现
除了以上问题之外,还有http请求分为很多方法(get/post/query…),如何根据不同的方法进行参数封装、调用等;
最后,还有其他一些基本的设计问题,面向对象设计的几大原则,内聚、耦合、可扩展等等

解读源码之前,先解释后面源码可能会遇到的成员以及类说明:
Retrofit中:
okhttp3.Call.Factory callFactory; okhttp底层网络调用引擎,网络都是由它去发起调用的
List<Converter.Factory> converterFactories; 转换器工厂类集合,需要用到的转换器都会add到这个集合
List<CallAdapter.Factory> adapterFactories; 调用适配器工厂类集合,需要用到的适配器都会add到这个集合
类ServiceMethod<R, T> :每个网络接口方法都会创建一个ServiceMethod,把请求和响应参数以及注解以及适配器、转换器都会封装到里面去
OkHttpCall以及OkHttpClient是最终网络处理中心

带着以上的问题,我们就从上面Retrofit.Builder()源码开始看看吧!


Retrofit.Builder

这是一个建造者模式的类,用于参数较多时,快速构建最终需要的Retrofit类:

==========Retrofit.java==========
public Builder() {
      this(Platform.get());
}
Builder(Platform platform) {
      this.platform = platform;
      converterFactories.add(new BuiltInConverters());
}
=======Retrofit.java=========

=======Platform.java=========
private static final Platform PLATFORM = findPlatform();
static Platform get() {
  return PLATFORM;
}
单利模式找到平台类,
private static Platform findPlatform() {
  try {
    Class.forName("android.os.Build");
    Android设备这里肯定不为0,所以PLATFORM=Android
    if (Build.VERSION.SDK_INT != 0) {
      return new Android();
    }
  } catch (ClassNotFoundException ignored) {
  }
}
Android是Platform的子类
static class Android extends Platform {
 返回主线程执行的Executor
 public Executor defaultCallbackExecutor() {
   return new MainThreadExecutor();
 }
 返回一个可以在主线程回调执行的调用适配器工厂类,记住他也是个调用适配器工厂类
 CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
   if (callbackExecutor == null) throw new AssertionError();
   return new ExecutorCallAdapterFactory(callbackExecutor);
 }
 主线程的Looper,这个线程任务最终会在主线程执行
 static class MainThreadExecutor implements Executor {
   private final Handler handler = new Handler(Looper.getMainLooper());
   @Override public void execute(Runnable r) {
     handler.post(r);
   }
 }
}
============Platform.java==============

Builder的默认构造方法获取一个Android平台类,它可以提供在主线程执行能力,返回后赋值给Builder的platform成员;在Builder(Platform platform)构造方法内,converterFactories成员是一个ArrayList集合,存储Converter.Factory类,这个是定义的一个抽象类,提供了java bean对象在http中的转换标准,而BuiltInConverters是提供的默认convert转换器,比如StringConvert、BufferConvert等等,默认的转换器一般用不到,所以看不懂BuiltInConverters里面的东西也没关系,这里看看Converter.Factory定义的接口:

public interface Converter<F, T> {
  javabean对象转换的方法,要从F类型转换为T类型
  T convert(F value) throws IOException;
  内部工厂类,用于提供不同功能的Convert
  abstract class Factory {
  	生产一个转换之前是ResponseBody类型,转换之后类型未知的Convert,用于响应时
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
      return null;
    }
    生产一个转换之后是RequestBody类型,转换之前类型未知的Convert,用于请求时
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }
	同上
    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
	获取index未知的参数类型Type
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }
	获取Type类型的class
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

从上述代码得知,java bean对象转换器做哪些工作了吧,实现他的接口即可,然后添加到Builder的converterFactories集合去;这里我们就看看我们自定义GsonConvert是不是这样的?


GsonConvert
public final class CustomGsonConverterFactory extends Converter.Factory {
 @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new CustomGsonResponseBodyConverter<>(gson, adapter);
    }   

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[]
                                                                  methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new CustomGsonRequestBodyConverter<>(gson, adapter);
    }   
}

响应转换器
final class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

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

    @Override
    public T convert(ResponseBody value) throws IOException {
        String response = value.string();
        HttpStatus httpStatus = gson.fromJson(response, HttpStatus.class);
        if (httpStatus.getcode != HttpStatus.success) {
            value.close();
            throw new ApiException(httpStatus.getCode(), httpStatus.getMessage(),httpStatus.getOperatorName());
        }   
        MediaType contentType = value.contentType();
        Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
        InputStream inputStream = new ByteArrayInputStream(response.getBytes());
        Reader reader = new InputStreamReader(inputStream, charset);
        JsonReader jsonReader = gson.newJsonReader(reader);
        try {
            return adapter.read(jsonReader);
        } finally {
            value.close();
        }   
    }   
}

这里我们确实是这么做的,重写请求响应方法,提供其转换器;使用了Gson库帮我们进行转换java对象,为了对网络请求错误统一,我们在Response里面对服务端返回的code做了判别处理,集中处理异常;回到Builder的.addConverterFactory(GsonConverterFactory.create())这里,builder源码:

public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
}

把转换器加入到了converterFactories集合中去


调用适配器CallAdapter

本篇文章前面说到了,调用适配器我们可以添加RXJava、LiveData和协程Coroutine等等不同的适配器,如果现在我们的Retrofit里面的adapterFactories集合已经存放了多个适配器了,那么我们在调用某一个具体网络方法如本文开始的test方法,那他该使用哪一个适配器呢?这就需要从众多适配器中去寻找,以接口返回值类型去匹配过滤,我们只需要定义好CallAdapter标准的返回值匹配能力即可,接口如下:

调用适配器T返回值类型  R是请求类型
public interface CallAdapter<R, T> {
  返回响应参数类型
  Type responseType();
  适配器发起网络调用
  T adapt(Call<R> call);

  abstract class Factory {
  	生成一个CallAdapter调用适配器,完成从R到T的转换,并且要调用网络
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);
	
	以下两个方法就是CallAdapter提供的参数匹配工具方法,快速查找到index处的参数类型以及class
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

上诉相关解释请看注释,然后我们在实现liveData适配器,只需要处理我们支持的接口方法返回值类型即可:

这个适配器只处理LiveData返回类型的网络接口方法
public class LiveDataCallAdapterFactory extends CallAdapter.Factory {
    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    	//我只能处理返回值类型为LiveData.class的
        if(getRawType(returnType) != LiveData.class){
            return null;
        }
        returnType泛型类型,获取第0处泛型类型
        Type type = getParameterUpperBound(0, (ParameterizedType) returnType);
        Class rawType = getRawType(type);
        如果0处类型不为ApiResponse,就不处理,抛错误,也就是LiveData<ApiResponse>
        if(rawType != ApiResponse.class){
            throw new IllegalArgumentException("type must be a resource");
        }

        if(!(type instanceof ParameterizedType)){
            throw new IllegalArgumentException("resource must be paramterized");
        }
        获取0处的参数类型,最终返回回来的是type类型即可
        type = getParameterUpperBound(0, (ParameterizedType) type);
        return new LivedataCallAdapter<Object>(type);
    }
}
真正的调用适配器,这是一个LiveData类型的
public class LivedataCallAdapter<T> implements CallAdapter<T, LiveData<ApiResponse<T>>> {
    private Type responseType;
    public LivedataCallAdapter(Type responseType) {
        this.responseType = responseType;
    }
    @Override
    public Type responseType() {
        return responseType;
    }
   adapt发起网络调用了,参数Call实质是一个OkhttpCall
    @Override
    public LiveData<ApiResponse<T>> adapt(final Call<T> call) {
        return new LiveData<ApiResponse<T>>() {
            private AtomicBoolean stat = new AtomicBoolean(false);
            @Override
            protected void onActive() {
                if(stat.compareAndSet(false, true)){
                	请求入队,执行网络操作
                    call.enqueue(new Callback<T>() {
                        @Override
                        public void onResponse(Call<T> call, Response<T> response) {
                        	将返回的数据发送到liveData中去,订阅了这个liveData的都可以收到
                            postValue(ApiResponse.Companion.<T>create(response));
                        }
                        @Override
                        public void onFailure(Call<T> call, Throwable t) {
                            postValue(ApiResponse.Companion.<T>create(t));
                        }
                    });
                }
            }
        };
    }
}

至此,CallAdapter适配器看完了;我们要记住Retrofit中有两个工厂类集合ArrayList,一个装转换java-bean对象的转换器Convert,另一个装发起网络调用的适配器CallAdapter;但是我们还不清楚这两个适配器是是如何组织起来使用?如何调用哪些方法,参数封装如何封装,最后又返回来是如何实现的?

带着问题,我们继续看Retrofit.Builder.build()

public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      okhttp3.Call.Factory callFactory = this.callFactory;
      因为我们没有传入callFactory,所以builder代替我们new一个OkHttpClient
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
	 callbackExecutor为null的,所以从platform获取默认的回调执行器,这个platform
	 前文讲过,defaultCallbackExecutor主要是获取一个能回到主线程执行的能力
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      这里把build进来的CallAdapter添加到adapterFactories去
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      同时这里也会添加一个默认的CallAdapter,这个默认的也能完成网络操作工作;
      所以如果你不添加调用适配器CallAdapter也是可以的
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      添加转换器Convert
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

=============================================================================
上诉代码会添加一个默认的调用适配器platform.defaultCallAdapterFactory(callbackExecutor),这个适配器可以自动把网络放到子线程操作,同时网络返回时,在返回到主线程,所以我们可以不添加其他的RXJava、LiveData等适配器,具体用法如下:

1. 定义这样的网络接口
@POST("xyyc/login/")
Call<LoginResponse> test(@Body LoginRequest request);
2. 调用
apiService.test(request)
  .enqueue(new Callback<LoginResponse>() {
        @Override
         public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
         }

        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) {
        }
    });

第二部回到Callback就已经在主线程执行了,是不是很方便!而且它也支持任务取消、终止等;虽然没有RXJava那样花里胡哨的功能强大,但是它简单快捷,代码量少,逻辑简单

=============================================================================


Retrofit

接着上面看到,Builder就已经把Retrofit创建给配置好了,然后就是Retrofit调用Create创建我们定义的接口类;下面代码要仔细看了,是Retrofit的核心逻辑:

参数service是我们定义的接口类class
 public <T> T create(final Class<T> service) {
   验证这个接口类是否有效,主要是判断是否为接口,并且该接口不能继承其他接口
   Utils.validateServiceInterface(service);
   是否需要快速使方法有效,怎么理解呢?就是把接口中的所有方法全部缓存起来,
   还是用一个缓存一个
   if (validateEagerly) {
     eagerlyValidateMethods(service);
   }
   这里就是用到了动态代理,让我们无法感知真实的类是哪个
   return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
       new InvocationHandler() {
         private final Platform platform = Platform.get();
		我们在调用某个网络操作方法时,就会执行到这里反射调用
         @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.
           调用method的类是否为Object,显然不是
           if (method.getDeclaringClass() == Object.class) {
             return method.invoke(this, args);
           }
           method是否为platform的默认方法  显示也不是
           if (platform.isDefaultMethod(method)) {
             return platform.invokeDefaultMethod(method, service, proxy, args);
           }
           逻辑周到这里了,根据调用方法的method从缓存中去取出
           ServiceMethod<Object, Object> serviceMethod =
               (ServiceMethod<Object, Object>) loadServiceMethod(method);
           创建一个OkHttpCall请求
           OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
           用callAdapter.adapt发起执行,这里是不是很熟悉,对了,你没猜错,这就是前文
           讲到的CallAdapter,他会执行adapt方法,在adapte方法发起网络调用,将这个okHttpCall
           入队enqueue到网络任务中去
           return serviceMethod.callAdapter.adapt(okHttpCall);
         }
       });
 }

这里我们看到发起调用是serviceMethod里面的callAdapter里面的adapt发起调用的,但是callAdapter装载到Retrofit集合里面去,可能有好几个,他怎么知道调用哪个呢?不慌,我们看看serviceMethod是如何来的,看以下代码:

这个就是快速缓存接口类的所有方法
private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    遍历接口类中所有的method
    for (Method method : service.getDeclaredMethods()) {
      默认都是false,所以都会执行loadServiceMethod
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
loadServiceMethod查找方法也会调用它,serviceMethodCache类型是ConcurrentHashMap,
key为method,value为ServiceMethod;为了保证并发效率,采用了分段锁
ServiceMethod<?, ?> loadServiceMethod(Method method) {
	先去serviceMethodCache集合中找,看是否找得到
  ServiceMethod<?, ?> result = serviceMethodCache.get(method);
  if (result != null) return result;
  双检测机制,保证查找效率
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      创建一个ServiceMethod并添加到缓存中去
      result = new ServiceMethod.Builder<>(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

因为后面的逻辑很多都和ServiceMethod有关,所以我们必须去ServiceMethod里面看看,它是如何被创建的?


ServiceMethod

首先从new ServiceMethod.Builder<>(this, method).build()这里开始:

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      获取这个method的所有注解
      this.methodAnnotations = method.getAnnotations();
      获取method的参数类型Type
      this.parameterTypes = method.getGenericParameterTypes();
      获取method参数的注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
}
构建一个serviceMethod
public ServiceMethod build() {
	得到这个method的调用适配器,看到没?这里已经绑定好了,每个ServiceMethod从
	一开始就绑定了调用适配器CallAdapter
      callAdapter = createCallAdapter();
      确定method返回类型
      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) {
      	这里主要是根据注解解析注解中的参数,比如@POST会有参数路径,以及body参数
      	设置好相对访问路径,参数等
        parseMethodAnnotation(annotation);
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
        获取每个参数的注解
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
		注解转换器,根据参数中不同的注解产生不同的处理句柄
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      return new ServiceMethod<>(this);
    }

上面的逻辑业务都在注释里面了,逻辑比较简单,但是仔细一看,会发现三个问题

(1)method怎么知道自己绑定哪个调用适配器CallAdapter ?
(2)同上,使用哪个转换器Convert ?
(3)参数如何封装进去,如POST方式的Body的请求是一个java对象,怎么弄到http的body ?


绑定调用适配器

话不多说,看源码:

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.");
  }
  获取方法method的注解
  Annotation[] annotations = method.getAnnotations();
  try {
    从Retrofit的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源码

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
    Annotation[] annotations) {
	start为0
  int start = adapterFactories.indexOf(skipPast) + 1;
  遍历所有的CallAdapter
  for (int i = start, count = adapterFactories.size(); i < count; i++) {
   调用每个CallAdapter的get方法,get方法返回他的适配器,这个get方法
   传入了method的返回值类型和方法注解
    CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
      return adapter;
    }
  }
}

再次回头看看CallAdapter的get方法,这里我们用自定义LiveData的

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
	首先就判断返回值类型是不是一个LiveData的class,如果不是就没必要执行了
	这个returnType就是我们定义网络接口方法的返回值类型
    if(getRawType(returnType) != LiveData.class){
        return null;
    }
    查看returnType的0处返回值类型,理解为泛型
    Type type = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class rawType = getRawType(type);
    泛型必须是APIResponse,后面类似
    if(rawType != ApiResponse.class){
        throw new IllegalArgumentException("type must be a resource");
    }

    if(!(type instanceof ParameterizedType)){
        throw new IllegalArgumentException("resource must be paramterized");
    }
    type = getParameterUpperBound(0, (ParameterizedType) type);
    就创建了LivedataCallAdapter调用适配器
    return new LivedataCallAdapter<Object>(type);
}

至此,调用适配器找到了;
做一个method绑定CallAdapter小结:
1 确定自己method的返回值returnType和注解annotation
2 遍历retrofit的所有CallAdapterFactory工厂类,并且依次工厂类的get方法
3 get方法中,会根据returnType是否支持,支持就返回创建调用适配器,不支持返回null
4 找到adapter就绑定到ServiceMethod中去

这里有两个个疑问如下:(1)Retrofit会为每个Method方法缓存到Map (2)每个Method都会绑定自己的适配器和转换器,并且大部分适配器和转换器都是new新的出来,而不是每个Method共用;结合上面两点,而网络访问接口类一般生命周期较长,这样会导致app的内存消耗较大,Retrofit为什么不根据网络接口来存储method,当某一个网络接口类死亡后,就销毁它里面提供的所有method,否则这个Retrofit的method缓存就会越来越大
当然他这个也可以解决,使用多个Retrofit,这样把Retrofit生命周期完结后,他这部分的缓存都会被清理掉,不过这个有点不合适


绑定转换器

绑定转换器和上面绑定调用适配器原理差不多,感兴趣可以自行去查看源码,这里就不继续阐述了


参数封装

参数封装也是一大核心点,比如GET我们可能传递的是动态路径,POST需要封装到Body中去,这里以Body封装为例,在ServiceMethod.Builder的build方法中有一句:parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations),就是为参数类型为parameterType,参数注解为parameterAnnotations提供一个参数处理句柄:

private ParameterHandler<?> parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler<?> result = null;
      因为注解annotation里面可能还有注解参数等
      for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);
		.......
      return result;
    }
private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
      if (annotation instanceof Url) {
      } else if (annotation instanceof Path) {
      } else if (annotation instanceof Query) {
      } else if (annotation instanceof QueryName) {
      } else if (annotation instanceof QueryMap) {
      } else if (annotation instanceof Header) {
      } else if (annotation instanceof HeaderMap) {
      } else if (annotation instanceof Field) {
      } else if (annotation instanceof FieldMap) {
      } else if (annotation instanceof Part) {
      } else if (annotation instanceof PartMap) {
      } else if (annotation instanceof Body) {
        if (isFormEncoded || isMultipart) {
          throw parameterError(p,
              "@Body parameters cannot be used with form or multi-part encoding.");
        }
        if (gotBody) {
          throw parameterError(p, "Multiple @Body method annotations found.");
        }

        Converter<?, RequestBody> converter;
        try {
          哈哈,终于找到了,找到转换器,这里会从retrfoit的转换工厂集合去找,也是根据type
          去找,找到了也要new一个绑定
          converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
        } catch (RuntimeException e) {
          // Wide exception range because factories are user code.
          throw parameterError(e, p, "Unable to create @Body converter for %s", type);
        }
        gotBody = true;
        return new ParameterHandler.Body<>(converter);
      }
      return null; // Not a Retrofit annotation.
    }

至此,ServiceMethod就构建好了,请求转换器/响应转换器Convert,调用适配器;

再次回到Retrofit的create方法中去,里面用到了动态代理调用方法,在动态代理的方法调用最后几句

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

发起调用

从上面代码可知,执行了serviceMethod.callAdapter适配器的adapt方法,这个adapt方法以我们自定义LiveData看看

	@Override
    public LiveData<ApiResponse<T>> adapt(final Call<T> call) {
        return new LiveData<ApiResponse<T>>() {
            private AtomicBoolean stat = new AtomicBoolean(false);
            @Override
            protected void onActive() {
                if(stat.compareAndSet(false, true)){
                	重点看这里,就是讲Call入队,这个Call是一个OkHttpCall
                    call.enqueue(new Callback<T>() {
                        @Override
                        public void onResponse(Call<T> call, Response<T> response) {
                            postValue(ApiResponse.Companion.<T>create(response));
                        }
                        @Override
                        public void onFailure(Call<T> call, Throwable t) {
                            postValue(ApiResponse.Companion.<T>create(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 {
        	createRawCall实质就是retrofit中OkHttpClien创建的RealCall
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

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

    if (canceled) {
      call.cancel();
    }
	将请求入队,并配置okhttp3.Callback()回调接口,这里实质就是Okhttp的用法了
	用过okhttp的都知道,这个就是okhttp的调用方式
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          网络响应java bean对象换砖
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        
      }

      private void callFailure(Throwable e) {
        ....
      }

      private void callSuccess(Response<T> response) {
       .....
      }
    });
  }
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
	......
	调用ServiceMethod的toResponse,进行对象转换,实质就是ServiceMethod里面的
	responseConvert,前文已讲过
 	T body = serviceMethod.toResponse(catchingBody);
	......
}

小结:
上面代码可以看出okhttp的调用逻辑,以及网络请求响应response的对象转换;但是还看不见请求参数是如何封装的?首先上面call会调用createRawCall创建,这个函数里面

private okhttp3.Call createRawCall() throws IOException {
	封装了请求参数,会使用到ServiceMethod之前绑定的RequestConvert
    Request request = serviceMethod.toRequest(args);
    callFactory是一个OkhttpClient,newCall是一个RealCall类型
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

最后就是把这个请求入队,交给okHttp底层的任务去了,OKHttp模块没有做过深入的研究,大致就是有几个任务队列,每个网络请求都会加到任务队列里面去,线程池的方式去这些任务队列中去取任务执行

至此,Retrofit的源码大致就分析完结!


总结

在这里插入图片描述
Retrofit主要的东西就是上面这些东西,转换器Convert提供java对象在Http传递过程中的转换能力,调用适配器CallAdapter提供了根据不能类型的网络访问方法不同的调用逻辑,而组织他们的关系都是ServiceMethod来实现的,根据每个网络接口方法的返回值类型、注解、请求参数格式等,保存到ServiceMethod中去,然后ServiceMethod根据这些信息从Retrofit的两个工厂类集合去搜寻属于自己的转换器Convert和调用适配器,然后封装请求参数、发起网络调用以及最后的网络返回响应数据转换等工作。

Retrofit的设计方式,在于把核心的工作都用统一的标准(接口)定义好,自己实现一些默认的能力,更多的则是由用户自己去实现,使Retrofit开发更自由化,根据自己的使用场景;所以,我们做设计时,不是把重要的内容自己实现,而是为重要内容定义标准,由使用者自己去实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气好男人_Jack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值