美文网首页Android精选
Retrofit2.0源码分析

Retrofit2.0源码分析

作者: 陈超_ | 来源:发表于2019-01-16 15:57 被阅读13次

    本文参考诸多博客,以及自己看源码分析。内容并非完全原创,写博客的目的只是让自己能够用文字去描述一遍源码实现,让自己总结一下。

    先了解一下Retorift的使用步骤

    1.创建retrofit实例
    2.创建网络请求接口实例
    3.进行网络请求
    4.处理网络请求回来的数据

    那么接下来就开始根据使用步骤一步一步分析

    1.创建retrofit实例

    创建Retrofit实例对象

    Retrofit retrofit = new Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(AppUrl.getHttpUrl())
                    .build();
    

    retrofit使用的是建造者模式,可以看出,build()以后返回的是Retrofit实例对象,所以肯定会去调用构造方法,所以先看一下Retrofit的构造方法

    Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
          List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
          Executor callbackExecutor, boolean validateEagerly) {
         // 网络请求器的工厂,默认使用okhttp
        this.callFactory = callFactory;
        // 网络请求的url地址
        this.baseUrl = baseUrl;
        // 数据转换器工厂的集合
        this.converterFactories = unmodifiableList(converterFactories); 
         //网络请求适配器工厂作用:生产网络请求适配器(CallAdapter)
        this.adapterFactories = unmodifiableList(adapterFactories);
        // 回调方法执行器
        this.callbackExecutor = callbackExecutor;
        //是否提前对业务接口中的注解进行验证转换的标志位
        this.validateEagerly = validateEagerly;
      }
    

    主要初始化了以上参数,就先大概熟悉一下上面几个参数具体是有什么作用
    接下来根据上面的参数一个一个的进行分析

    CallAdapter(网络请求执行器Call的适配器)

    callAdapter默认是使用OkHttpCall,以下代码来自Platform内部实现
    在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory

    接下来就继续分析Builder这个类,部分代码已经删掉了,留下一些代码分析

    public static final class Builder {
        private Platform platform;
        private okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        private List<Converter.Factory> converterFactories = new ArrayList<>();
        private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private Executor callbackExecutor;
        private boolean validateEagerly;
    
        Builder(Platform platform) {
          this.platform = platform;
          converterFactories.add(new BuiltInConverters());
        }
    
      //会调用这个无参构造,this再去调用有参构造
        public Builder() {
          this(Platform.get());
        }
    

    那就先看看Platform里面都

    class Platform {
    
     // 将findPlatform()赋给静态变量
      private static final Platform PLATFORM = findPlatform();
     
      static Platform get() {
        return PLATFORM;    
      }
    
    //以下代码可以看出,支持3个平台:Android平台、Java平台、IOS平台
    private static Platform findPlatform() {
        try {
          // Class.forName(xxx.xx.xx)的作用:要求JVM查找并加载指定的类(即JVM会执行该类的静态代码段)
          Class.forName("android.os.Build");
          if (Build.VERSION.SDK_INT != 0) {
          // 如果是Android平台,就创建一个Android对象返回
            return new Android();
          }
        } catch (ClassNotFoundException ignored) {
        }
        //java平台
        try {
          Class.forName("java.util.Optional");
          return new Java8();
        } catch (ClassNotFoundException ignored) {
        }
        //ios平台
        try {
          Class.forName("org.robovm.apple.foundation.NSObject");
          return new IOS();
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform();
      }
    

    因为我们是Android平台,所以看一下Android的内部实现

     static class Android extends Platform {
        //创建默认的网络请求适配器工厂
        @Override public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        // 返回一个默认的回调方法执行器
        @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
    
        static class MainThreadExecutor implements Executor {
          // 获取Android主线程绑定的Handler 
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    

    再分析一下GsonConverterFactory.create()

    public final class GsonConverterFactory extends Converter.Factory {
    
      public static GsonConverterFactory create() {
      //创建Gson对象
        return create(new Gson());
      }
    
      public static GsonConverterFactory create(Gson gson) {
      //创建了包含Gson对象实例的GsonConverterFactory
        return new GsonConverterFactory(gson);
      }
    
      private final Gson gson;
    
      private GsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
      }
    }
    

    从上面这段代码可以看出,GsonConverterFactory.create()实际上就是创建了一个含有Gson对象的GsonConverterFactory,再看看addConverterFactory的内部实现,实际上就是把GsonConverterFactory添加到了数据转换器工厂的集合当中

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

    再来分析一下baseUrl执行了什么操作,baseUrl(“www.baidu.com”)

    public Builder baseUrl(String baseUrl) {
        //判断url是否为空
          checkNotNull(baseUrl, "baseUrl == null");
        //转换为Okhttp的HttpUrl类型
          HttpUrl httpUrl = HttpUrl.parse(baseUrl);
          if (httpUrl == null) {
            throw new IllegalArgumentException("Illegal URL: " + baseUrl);
          }
          return baseUrl(httpUrl);
        }
    
    public Builder baseUrl(HttpUrl baseUrl) {
          checkNotNull(baseUrl, "baseUrl == null");
          List<String> pathSegments = baseUrl.pathSegments();
          //检查URL参数是不是以"/"结尾
          if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
            throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
          }
          this.baseUrl = baseUrl;
          return this;
        }
    

    由此得知,url会转换为Okhttp的HttpUrl类型,并且Url一定要以"/"结尾,否则会抛出异常。
    最后再分析一下,.build()方法。

    public Retrofit build() {
          //判断请求url地址是否为空
          if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
          }
    
          okhttp3.Call.Factory callFactory = this.callFactory;
          //如果没有指定,默认用OkHttpClient
          if (callFactory == null) {
            callFactory = new OkHttpClient();
          }
    
          //如果没有指定,会默认使用MainThreadExecutor
         //之前已经判断了当前环境是Android,而继承自Platform的Android里面已经提供了默认的
          Executor callbackExecutor = this.callbackExecutor;
          if (callbackExecutor == null) {
            callbackExecutor = platform.defaultCallbackExecutor();
          }
    
          //添加网络请求适配器工厂到集合当中,默认适配器工厂(ExecutorCallAdapterFactory)添加到集合最后
          List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
          adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
          //数据转换器工厂 1.默认的数据转换工厂 2.自定义的数据转换工厂
          List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
        
          //最终返回Retrofit的对象,并传入已经配置好的成员变量
          return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);
        }
    

    2.创建网络请求接口实例

    //定义接收网络数据的类
    public interface HttpService {
        //   app版本检查
        //注解GET:采用Get方法发送网络请求
        @GET("app/version/get-newversioninfo?versionCode=1")
        // 接受网络请求数据的方法
        Call<JavaBean> newVersionInfo();
    }
    
    HttpService httpService = retrofit.create(HttpService.class);
    
    Call<JavaBean> call = httpService.newVersionInfo();
    

    接下来就看看retrofit.create(service)到底做了什么。

    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() {  // 将代理类的实现交给 InvocationHandler类作为具体的实现
              private final Platform platform = Platform.get();
              @Override public Object invoke(Object proxy, Method method, Object... args)
                  throws Throwable {
               
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                //主要就是一下三行代码的实现,下面再具体分析这三行代码
                ServiceMethod serviceMethod = loadServiceMethod(method);
                OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    
    private void eagerlyValidateMethods(Class<?> service) {
        //获取当前系统环境
        Platform platform = Platform.get();
        //获取本类中的所有方法,包含private,protected以及默认权限
        for (Method method : service.getDeclaredMethods()) {
          if (!platform.isDefaultMethod(method)) {
            //将传入的ServiceMethod对象加入LinkedHashMap<Method, ServiceMethod>集合
            loadServiceMethod(method);
          }
        }
      }
    
      ServiceMethod loadServiceMethod(Method method) {
        ServiceMethod result;
        synchronized (serviceMethodCache) {
        //先通过key获取ServiceMethod(以Method为键将该对象存入LinkedHashMap集合中)
          result = serviceMethodCache.get(method);
        //如果ServiceMethod为空,则创建ServiceMethod并添加
          if (result == null) {
            result = new ServiceMethod.Builder(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    

    前面提到invoke有三行代码,现在开始分析这三行代码,loadServiceMethod在上面已经大概添加了注解了,继续看loadServiceMethod方法中的new ServiceMethod.Builder(this, method).build() 具体内部实现

    final class ServiceMethod<T> {
      static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
      static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
      static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
       // 网络请求工厂  
      final okhttp3.Call.Factory callFactory;
       //网络请求适配器工厂
      final CallAdapter<?> callAdapter;
      // 网络请求地址 
      private final HttpUrl baseUrl;
      // Response内容转换器
      private final Converter<ResponseBody, T> responseConverter;
      // 网络请求的Http方法 
      private final String httpMethod;
      // 网络请求的相对地址
      private final String relativeUrl;
      // 网络请求的http请求头
      private final Headers headers;
      // 网络请求的http报文body的类型
      private final MediaType contentType;
      private final boolean hasBody;
      private final boolean isFormEncoded;
      private final boolean isMultipart;
      private final ParameterHandler<?>[] parameterHandlers;
      ServiceMethod(Builder<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;
        }
    }
    

    通过上面的代码可以知道,SeviceMethod包含了网络请求的基本信息
    再看看build的实现

    public ServiceMethod build() {
          // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器
          callAdapter = createCallAdapter();
          // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型
          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?");
          }
          // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器
          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.");
            }
            //为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
            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);
        }
    
    private CallAdapter<?> 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.");
          }
    
          // 获取网络请求接口接口里的注解
          // 此处使用的是@Get
          Annotation[] annotations = method.getAnnotations();
          try {
            return 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);
          }
        }
    
    private Converter<ResponseBody, T> createResponseConverter() {
          Annotation[] annotations = method.getAnnotations();
          try {
            return retrofit.responseBodyConverter(responseType, annotations);
          } catch (RuntimeException e) { // Wide exception range because factories are user code.
            throw methodError(e, "Unable to create converter for %s", responseType);
          }
        }
    
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, 
        Annotation[] annotations, Retrofit retrofit) {
    
      
      TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
      // 根据目标类型,利用 Gson#getAdapter 获取相应的 adapter
      return new GsonResponseBodyConverter<>(gson, adapter);
    }
    
    // 做数据转换时调用 Gson 的 API 即可。
    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 {
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
          return adapter.read(jsonReader);
        } finally {
          value.close();
        }
      }
    }
    

    相关文章

      网友评论

        本文标题:Retrofit2.0源码分析

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