Retrofit源码学习之一

我们从简单的使用开始

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

Retrofit 使用方法注解的方式把Java接口转化成HTTP请求

首先我们声明接口

public interface GitHubService {
   //获取github上用户信息
   @GET("users/{user}")
   Call userInfo(@Path("user") String user);
}

Retrofit使用四部曲

  1. 构建一个Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .build();
  1. 生成一个GitHubService接口的实现
GitHubService service = retrofit.create(GitHubService.class);
  1. 创建一个请求
Call call = service.userInfo("humanheima");

4.同步或者异步执行请求

4.1 同步请求

try {
    Response response = call.execute();
} catch (IOException e) {
    e.printStackTrace();
}

注意不要在主线程直接调用,不然会抛出android.os.NetworkOnMainThreadException

4.2 异步执行

call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            ResponseBody body = response.body();
            if (body != null) {
                try {
                    Log.d(TAG, "onResponse: " + body.string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {

        }
});

1.构建一个Retrofit实例。

首先看一下Retrofit.Builder类的构造函数

public Builder() {
    this(Platform.get());
}

Builder(Platform platform) {
    this.platform = platform;
}

Retrofit.Builder类的构造函数内部初始化了一个Platform实例。Platform代表Retrofit的使用平台。我们在Android中使用Retrofit,平台就是Android。

static class Android extends Platform {
    //默认的回调执行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
    //看到了Handler。可以猜想,回调之所以是在主线程执行,还是使用handler来实现的  
      private final Handler handler = new Handler(Looper.getMainLooper());

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

接下来看一下Retrofit.Builder类的build方法

public Retrofit build() {
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }
    //注释1处,初始化callFactory 
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
        callFactory = new OkHttpClient();
    }
    //初始化回调执行器
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        //注释2处,使用平台默认的回调执行器
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    //注释3处,防御性拷贝callAdapterFactories,并添加默认的CallAdapter.Factory
    List callAdapterFactories = new ArrayList<>
                                               (this.callAdapterFactories);
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    //注释4处,防御性拷贝converters,并添加内置的converter factory 
    List converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());
    //首先添加内置的converter factory到converter factory list中
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    //创建Retrofit实例
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

注释1处,创建了一个OkHttpClient对象。

注释2处,如果没有传入回调执行器,则使用平台默认的回调执行器,在Android平台中就是一个MainThreadExecutor对象。

注释3处,添加了平台默认的CallAdapter.Factory。就是一个ExecutorCallAdapterFactory对象,传入的是MainThreadExecutor对象。

注释4处,首先添加了一个内置的Converter.Factory对象。是一个BuiltInConverters对象。

最后Retrofit.Builder类的build()方法返回了一个Retrofit实例。

Retrofit的构造函数

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List converterFactories, List callAdapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;//是一个OkHttpClient对象
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; 
    this.callAdapterFactories = callAdapterFactories; 
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
}

2. 生成一个GitHubService接口的实现

GitHubService service = retrofit.create(GitHubService.class);

Retrofit的create 方法

public  T create(final Class service) {
    //1. 首先验证service是否合法
    Utils.validateServiceInterface(service);
    //2. 是否提前创建service里面的所有方法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //3. 创建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 {
             // service的所有方法调用,最终会转发到这里
            // 如果是Object的方法,就正常调用
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //如果是default方法(Java8中的默认方法),Android中不用管,一定是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //3.1
            ServiceMethod serviceMethod =(ServiceMethod) 
                loadServiceMethod(method);
            //3.2
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //3.3
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
      });
  }
 
 

create方法内部创建了我们传入的service接口的动态代理。就是说我们我们调用service中的任何方法,都会转发到这个动态代理的invoke方法中。

3. 创建一个请求

Call call = service.userInfo("humanheima");

这时方法就转发到service动态代理的invoke方法中了。

//3.1
ServiceMethod serviceMethod =(ServiceMethod) loadServiceMethod(method);
//3.2
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//3.3
 return serviceMethod.callAdapter.adapt(okHttpCall);

 
 
3.1构建一个ServiceMethod实例,ServiceMethod把对接口方法的调用转为一个HTTP调用
//缓存ServiceMethod实例
private final Map> serviceMethodCache = new
 ConcurrentHashMap<>();

Retrofit的loadServiceMethod方法

ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //注释1处
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
}

首先在缓存中查找method对应的ServiceMethod,如果缓存中存在就直接返回,否则创建一个ServiceMethod并加入缓存。每个ServiceMethod只会创建一次。

接下来看一下ServiceMethod.Builder这个类。ServiceMethod.Builder负责检查接口方法上的注解,来构造一个可重复使用的服务方法。这个过程需要用到代价非常昂贵的反射操作,所以最好是只构建一个方法一次,然后重复使用它。Builder的实例不能被重用。

ServiceMethod.Builder的构造函数

Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    this.methodAnnotations = method.getAnnotations();
    this.parameterTypes = method.getGenericParameterTypes();
    this.parameterAnnotationsArray = method.getParameterAnnotations();
}

ServiceMethod.Builder的build方法简化版

public ServiceMethod build() {
    //1. 创建callAdapter
    callAdapter = createCallAdapter();
    //在这个例子中responseType就是ResponseBody
    responseType = callAdapter.responseType();
    ...
    //2. 创建responseConverter
    responseConverter = createResponseConverter();
    //3. 处理方法注解
    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
    }
    ...
    int parameterCount = parameterAnnotationsArray.length;
    //4. 创建parameterHandlers
    parameterHandlers = new ParameterHandler[parameterCount];
    for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
    }
    ...
    //5. 返回一个ServiceMethod实例
    return new ServiceMethod<>(this);
}

  1. 创建callAdapter。CallAdapter对象把一个类型参数为R的retrofit2.Call转化成T类型的对象(Call转化成T)。CallAdapter的实例由构建Retrofit时候通过{Retrofit.Builder#addCallAdapterFactory(Factory)}方法设置的{CallAdapter.Factory}创建。

ServiceMethod.Builder类的createCallAdapter方法简化版

private CallAdapter createCallAdapter() {
    //获取方法返回类型,在这个例子中,返回类型是Call
    Type returnType = method.getGenericReturnType();
    ...
    //获取方法注解
    Annotation[] annotations = method.getAnnotations();
    try {
      //注释1处,根据方法的返回类型和方法注解返回CallAdapter
      return (CallAdapter) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) {
        throw methodError(e, "Unable to create call adapter for %s", returnType);
    }
}

注释1处,根据方法的返回类型和方法注解返回CallAdapter。

Retrofit的callAdapter方法

public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
}

Retrofit的nextCallAdapter方法简化版

 public CallAdapter nextCallAdapter(CallAdapter.Factory skipPast, 
    Type returnType, Annotation[] annotations) {
   
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        //注释1处,遍历callAdapterFactories,返回合适的CallAdapter
        CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
        if (adapter != null) {
            return adapter;
        }
    }
}

Retrofit的callAdapter()方法内部会去遍历callAdapterFactories这个list,根据方法返回类型和注解,返回合适的callAdapter。

在上面的分析中,当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部默认添加了一个平台相关的CallAdapter.Factory而Android平台相关的默认的CallAdapter.Factory就是一个ExecutorCallAdapterFactory对象。ExecutorCallAdapterFactory这个类暂且不去管他。默认情况下ServiceMethod 的callAdapter就是ExecutorCallAdapterFactory的get方法返回的对象。

  1. 创建Converter responseConverter。负责把okhttp3.ResponseBody转化为T类型的对象。
private Converter createResponseConverter() {
    Annotation[] annotations = method.getAnnotations();
    try {
        //注释1处,根据方法的返回类型和注解返回Converter
        return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { 
        throw methodError(e, "Unable to create converter for %s", responseType);
    }
}

可见responseConverter也是由Retrofit提供的。

public  Converter responseBodyConverter(Type type, 
    Annotation[] annotations) {

    return nextResponseBodyConverter(null, type, annotations);
}

public  Converter nextResponseBodyConverter(
       Converter.Factory skipPast, Type type, Annotation[] annotations) {
 
    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
         //注释1处,遍历converterFactories,找到合适的converter
        Converter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
        if (converter != null) {
            return (Converter) converter;
        }
    }
}

Retrofit的responseBodyConverter()方法内部会去遍历converterFactories这个list,根据方法返回类型和注解,返回合适的responseConverter。
在上面的分析中,当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部传入了一个内置的BuiltInConverters对象。BuiltInConverters这个类暂且不去管它。现在为ServiceMethod找到了responseConverter。

  1. parseMethodAnnotation:负责解析检查方法注解,暂且略过。

  2. 创建parameterHandlers,内部会创建Converter,负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;这个过程暂且不去看。

每个参数都会有一个 ParameterHandler,由 ServiceMethod的parseParameter 方法负责创建,其主要工作就是解析每个参数使用的注解类型(诸如 Path,Query,Field 等),对每种类型进行单独的处理。API 方法中除@Body@PartMap@Part类型的参数,都利用 Converter.Factory.stringConverter 进行转换。而@Body@PartMap@Part类型的参数则利用 Converter.Factory.requestBodyConverter 进行转换。

现在ServiceMethod.Builder的build()方法可以返回一个实例了。

public ServiceMethod build() {
    //5. 返回一个ServiceMethod实例
    return new ServiceMethod<>(this);
}

ServiceMethod的构造函数

ServiceMethod(Builder 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;
}
3.2是创建一个OkHttpCall实例
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 
 
3.3 返回结果
return serviceMethod.callAdapter.adapt(okHttpCall);

ServiceMethod的adapt方法

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

默认情况下,ServiceMethod的callAdapter就是ExecutorCallAdapterFactory的get方法返回的对象。

ExecutorCallAdapterFactory的get方法

@Override
public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
        return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    //返回一个CallAdapter实例。
    return new CallAdapter>() {
      @Override public Type responseType() {
          return responseType;
      }

      @Override public Call adapt(Call call) {
            //注释1处,返回ExecutorCallbackCall实例
            return new ExecutorCallbackCall<>(callbackExecutor, call);
        }
    };
}

 
 

ExecutorCallAdapterFactory的get方法创建了一个CallAdapter的匿名对象。该对象的
adapt方法返回了一个ExecutorCallbackCall对象。

注意,到这里Call call = service.userInfo("humanheima");方法最终返回的是一个ExecutorCallbackCall对象。ExecutorCallbackCall类是ExecutorCallAdapterFactory的静态内部类,实现了retrofit2.Call接口。

ExecutorCallbackCall的构造函数

static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;//回调执行器
    final Call delegate;//一个OkHttpCall对象

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
}

注意一下,在Android平台下,我们传入的回调执行器是一个MainThreadExecutor对象,用来将执行结果post到主线程,我们下面分析。

4. 现在到了Retrofit使用四部曲的第四步,执行请求。

4.1 同步请求execute

ExecutorCallbackCall的execute方法就是调用了代理对象的execute方法。

@Override 
public Response execute() throws IOException {
    return delegate.execute();
}

OkHttpCall的execute方法

@Override 
public Response execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      //1. 一个请求只能被执行一次
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      //...
      call = rawCall;
      if (call == null) {
        try {
          //2. 创建一个okhttp3.Call
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    //3. 转换okhttp3.Call的执行返回的响应
    return parseResponse(call.execute());
  }
  1. 一个请求只能被执行一次。
  2. 调用createRawCall方法,创建一个okhttp3.Call

OkHttpCall的createRawCall方法

private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

createRawCall方法返回的是一个okhttp3.RealCall的实例。

  1. 转换okhttp3.Call的执行返回的响应retrofit2.Response
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    //临时保存原始响应体
    ResponseBody rawBody = rawResponse.body();

    //移除响应体的源(唯一有状态的对象),这样我们就可以传递响应。
    //移除rawResponse的本来的响应体,传入一个没有内容的响应体
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    //...
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      //注释1处,把原始响应体转化成我们希望的数据类型
      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;
    }
  }

parseResponse方法首先会对响应做一些预处理,如果没有什么异常的话,就构建一个成功的响应返回。

在注释1处,在这个例子中,我们期望返回的数据类型就是okhttp3.ResponseBody

ServiceMethod的toResponse方法

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}

内部调用了responseConverter的convert方法,在上面的分析中,我们知道默认情况下responseConverter就是BuiltInConverters的responseBodyConverter方法返回的对象。

final class BuiltInConverters extends Converter.Factory {
    @Override
    public Converter responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      //我们的返回类型是ResponseBody
      if (type == ResponseBody.class) {
        //注释1处,我们只看没有使用Streaming注解的情况
        return Utils.isAnnotationPresent(annotations, Streaming.class)
            ? StreamingResponseBodyConverter.INSTANCE
            : BufferingResponseBodyConverter.INSTANCE;
      }
      if (type == Void.class) {
        return VoidResponseBodyConverter.INSTANCE;
      }
      return null;
    }
}

在注释1处,我们只看没有使用Streaming注解的情况,返回的是一个BufferingResponseBodyConverter对象。

BufferingResponseBodyConverter类

static final class BufferingResponseBodyConverter implements Converter {

    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
          // 注释1处,缓存整个响应体避免将来出现IO异常
          return Utils.buffer(value);
      } finally {
          value.close();
      }
  }
}

在注释1处,就是返回了整个响应体。

static ResponseBody buffer(final ResponseBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.source().readAll(buffer);
    return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
}

最终执行的结果是返回了一个Response对象。

4.2 异步请求execute

ExecutorCallbackCall内部的execute就是调用了代理对象的execute方法。执行完毕后会使用传入的callbackExecutor执行线程切换。

@Override 
public void enqueue(final Callback callback) {
    //调用代理的enqueue方法,并在执行完毕后使用回调执行器切换线程
    delegate.enqueue(new Callback() {
      @Override 
      public void onResponse(Call call, final Response response) {
          //注释1处,执行成功,使用回调执行器切换线程
          callbackExecutor.execute(new Runnable() {
          @Override 
          public void run() {
              if (delegate.isCanceled()) {
                //如果请求被取消了,抛出IOException
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override
        public void onFailure(Call call, final Throwable t) {
            //执行失败,切换线程
            callbackExecutor.execute(new Runnable() {
            @Override
            public void run() {
                callback.onFailure(ExecutorCallbackCall.this, t);
            }
        });
      }
  });
}   

OkHttpCall的enqueue方法

@Override 
public void enqueue(final Callback callback) {
 
    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 {
          //1.构建一个okhttp3.Call   
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    //...
    if (canceled) {
      call.cancel();
    }
    //2. 使用okhttp3.Call的enqueue方法
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response response;
        try {
          //把okhttp3.Response转换成retrofit2的Response  
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        //3. 成功的回调
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          //4. 失败的回调  
          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 response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

OkHttpCall的enqueue方法先判断请求是否执行过了。如果没有执行,就构建一个okhttp3.Call的实例,加入一个异步请求队列,执行成功或者失败后会调用传入的callback的对应方法。

如果执行成功,调用传入的callback的onResponse方法。

delegate.enqueue(new Callback() {
      @Override 
      public void onResponse(Call call, final Response response) {
          //注释1处,调用回调执行器execute的方法切换线程
          callbackExecutor.execute(new Runnable() {
          @Override 
          public void run() {
              if (delegate.isCanceled()) {
                //如果请求被取消了,抛出IOException
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }
    //...
}

在注释1处,使用回调执行器切换线程。在Android中就是一个MainThreadExecutor对象。我们看一下MainThreadExecutor的execute方法。

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

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

内部就是通过handler来切换到了主线程。

listCall.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            //回到主线程执行
            ResponseBody body = response.body();
            if (body != null) {
                try {
                    Log.d(TAG, "onResponse: " + body.string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
             //回到主线程执行
        }
});

至此:Retrofit使用四部曲就分析完了。

参考链接

  1. Retrofit
  2. Android Retrofit 2.0使用
  3. github
  4. 拆轮子系列:拆 Retrofit

你可能感兴趣的:(Retrofit源码学习之一)