Retrofit2源码解析(一)

一、适用人群。会使用Retrofit,想更好更全面的了解Retrofit的童鞋。

二、解析
1、获取Retrofit实例

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

成员变量解释
1)callFactory 处理网络请求的工厂类,依赖于okhttp3.Factory
2)baseUrl 网络请求的基础地址
3)converterFactories 实例类转化工厂
4)adapterFactories CallAdapter生成工厂
5)callbackExecutor 回调的执行者,一个executor
6)validateEagerly 是否提前验证methods是实现自接口

这里着重说下converterFactories 和adapterFactories 的区别和作用

在Rxjava中,网络请求的接口一般是这种形式

    public interface HttpLogin {
        @POST("account/login")
        XXX<YYY> login(@Body ZZZ body);
    }

converterFactories 是负责文字和实体类互相转化,需要把http返回的body转成yyy实体类,以及把ZZZ实体转成字符串。
adapterFactories 是负责生成XXX实体类的适配器。在DefaultCallAdapterFactory.java文件中可以看出陆默认的仅支持XXX为retrofit2.Call类型

看下默认赋值

public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

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

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

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

可以看出:
1) 必须设置baseUrl
2)默认使用okhttp3.OkHttpClient使用网络请求工厂
3)callbackExecutor回调执行器用的是MainThreadExecutor,简单的说就是在主线程回调

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

4)adapterFactories默认添加了retrofit2.DefaultCallAdapterFactory

DefaultCallAdapterFactory.class
 */
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  //可以看出支持的返回类型仅为retrofit2.Call,其他类型就不支持了
    if (getRawType(returnType) != Call.class) {
      return null;
    }

    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public <R> Call<R> adapt(Call<R> call) {
        return call;
      }
    };
  }
}

5)converterFactories默认是个retrofit2.BuiltInConverters

retrofit2.BuiltInConverters代码太多,就只贴出关键的
//可以看出只支持入参为ResponseBody类型
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
        return StreamingResponseBodyConverter.INSTANCE;
      }
      return BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

6)validateEagerly默认flase;

2、根据上面的要求创建一个请求接口

    public interface HttpLogin {
        @POST("account/login")
        retrofit2.Call<ResponseBody> login(@Body RequestBody body);
    }

1) retrofit2.Call login = retrofit.create(HttpLogin.class)
.login(RequestBody.create(MediaType.parse(“Application/json”), “{\”account\”:112333}”));
这里看下Retrofit.create(final Class service) 函数

   public <T> T create(final Class<T> service) {
   //验证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, Object... args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            //如果该方法在的类.class是Object.class
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

            //如果是平台的默认方法,在Android Platform恒为false。
            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);
          }
        });
  }

这里出现了ServiceMethod,发现对它不了解的话就无法进行下去了。我们来看看
ServiceMethod类

public ServiceMethod.Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //方法的注解集
      this.methodAnnotations = method.getAnnotations();
      //方法的参数类型集
      this.parameterTypes = method.getGenericParameterTypes();
      //方法的参数注解集(@path.etc)
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }
//这里只展现了一些核心代码
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);
      }

        //解析接口的入参与入参注解
      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);
        }
      }

      return new ServiceMethod<>(this);
    }
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;
  }

这时候得到了retrofit2.Call login对象,这个call很像Okhttp里的Call;

这时候调用

   login.enqueue(new retrofit2.Callback<ResponseBody>() {
            @Override
            public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                System.out.println("onResponse ");
                try {
                    System.out.println(response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
                System.out.println("onFailure " + t.getMessage());
            }
        });
        实际上调用了retrofit2.OkHttpCall<T>. enqueue(final Callback<T> callback)方法

 @Override public void enqueue(final Callback<T> callback) {
    if (callback == null) throw new NullPointerException("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) {
          failure = creationFailure = t;
        }
      }
    }

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

    if (canceled) {
      call.cancel();
    }

//这里是调用了okhttp.call的方法
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }
执行完。控件台打印出
onResponse 
{"code":999999,"des":"参数错误[密码不能为空]"}

Process finished with exit code 0