通过Retrofit2来看http

通过Retrofit2来看http

  • 什么是retrofit2通过Retrofit2来看http_第1张图片

从字面理解retrofit2就是用于Android和java平台的类型安全可靠的http请求框架。什么是类型安全呢,所谓类型安全就是编译阶段就已经做了类型检查,在程序运行阶段不会报类型错误。

上述文字是官网描述,这里个人再补充一点,retrofit2实际上是对http请求的一个封装,底层还是通过okhttp进行网络请求的,本节只对retrofit2进行源码分析,后续会补充okhttp的源码分析。

  • retrofit2的简单使用

1.定义一个java接口以及http请求方法

public interface GitHubService {
  @GET("users/{user}/repos")
  Call> listRepos(@Path("user") String user);
}

2.构造Retrofit实例,可配置baseUrl

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    . addConverterFactory(GsonConverterFactory.create())
    .build();

3.调用Retrofit实例的create方法生成GitHubService接口实例

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

4.调用GitHubService的listRepos方法获取Call对象

Call> repos = service.listRepos("octocat");

5.通过Call对象去获取请求

repos.enqueue(new Callback() {
    @Override
    public void onResponse(Call> call, Response> response) {
    
    }
    @Override
    public void onFailure(Call> call, Throwable t) {
    }
});
  • retrofit2的源码解读
    简单使用了解过后,接下来进行源码解读。该怎么读源码呢,博主的方法不是一行一行的去读,而是从入口去读,即从正在使用的地方去读,读懂过整个流程和框架,不过分去弄清每一行代码,要不然大把的时间耗费在里面得不偿失。

1.先来看看Retrofit的构造方法,看到builder()就知道是构造者模式创建的Retrofi实例,
这里只贴关键部分代码


    //使用的平台 Android 或者 java
    private final Platform platform;

	//用于网络请求的OkHttpClient
    private @Nullable okhttp3.Call.Factory callFactory;

   //请求服务器的baseUrl地址
    private HttpUrl baseUrl;

   //数据转换器工厂
    private final List converterFactories = new ArrayList<>();

   //网络适配器工厂
    private final List adapterFactories = new ArrayList<>();

    //任务执行器
    private @Nullable Executor callbackExecutor;

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();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List converterFactories = new ArrayList<>(this.converterFactories);

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

这里重点关注callFactory,converterFactories,callFactory,callbackExecutor这几个对象,这里可以看到如果用户不自定callFactory,则new 一个 OkHttpClient对象。通过上述几个对象构造了Retrofit对象。

public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }
·······················································
if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

然后我们看下callbackExecutor,通过platform.defaultCallbackExecutor()得到,我们先看看platfor是怎么获取的,platform = Platform.get();点击get()方法进去,

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

·········
}

可以看到返回PLATFORM,即findPlatform()方法,当Build.VERSION.SDK_INT != 0满足条件时,返回一个新生成的Android对象,否则返回一个Java8对象。再来看看Android类如下,所以 platform.defaultCallbackExecutor()返回的任务执行器实际上就是MainThreadExecutor对象,持有handler属性将异步任务会调到主线程中去。

 static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

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

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

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
List adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

接下来看看adapterFactories,无论是否自定义CallAdapter.Factory,都会在集合里面添加一个factory,可以看出是一个ExecutorCallAdapterFactory对象,并且将callbackExecutor作为参数传了进去。咱们先不看具体的ExecutorCallAdapterFactory类实现,回到主线代码来。

获取到Retrofit对象以后,执行create方法,点击进去

 public  T create(final Class service) {
   //验证interface接口,这里不贴具体代码了
   //1.首先验证是否是接口
   //2.验证是否有继承关系,Retrofit不允许此接口有继承关系
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
		//3.提前加载接口中的method
      eagerlyValidateMethods(service);
    }
    
    //4.动态代理
    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) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
 
  

这里最关键的第4点动态代理,可以说动态代理就是Retrofit的核心所在,具体动态代理的内容就不这讲了。create方法传入了GitHubService.class参数,这里动态代理的是GitHubService对象。执行这个代理的listRepos方法相当于执行InvocationHandler的invoke方法,这就解释了为什么只写了一个接口,一个方法名,和一些注解以及一些参数就能进行网络请求了,所有这些工作都是在这个invoke方法里做的,所以我们重点看下这个invoke方法。

			//如果该方法直接来自Object类,例如equals(),toString()等,则直接调用
           if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

			//默认false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
 
  

我们先看看loadServiceMethod这个方法,先去缓存里取,如果有则返回,没有则生成一个ServiceMethod对象,然后放入到缓存中去,并且返回这个ServiceMethod对象。

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

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

我们可以先偷看看这个ServiceMethod类

 private final HttpUrl baseUrl;
  private final Converter responseConverter;
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler[] parameterHandlers;

  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;
  }

  Request toRequest(@Nullable Object... args) throws IOException {
  		``````
  }
  
  /** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

通过Retrofit2来看http_第2张图片
看到这里,你会不会有种恍然大悟的感觉,httpMethod,relativeUrl,headers…这些参数是不是似曾相识,再看看方法名toRequest,构造一个request请求,toResponse,构造一个reponse响应,所以ServiceMethod类才是retrofit中的重中之重,所有的操作都是通过这个类完成的。

再来看下一行通过serviceMethod,args构造了一个OkHttpCall对象,熟悉动态代理的同学应该知道,这里的args就是接口GitHubService里具体方法的参数数组。同样我们也看下OkHttpCall类,会发现里面有两个很重要的方法,一个是enqueue方法,一个是execute方法,到这里先不看具体实现,回到主线来。

 OkHttpCall(ServiceMethod serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

@Override 
public void enqueue(final Callback callback) {
     ............
  }

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

继续往下走,这里贴下代码。

return serviceMethod.callAdapter.adapt(okHttpCall);

其中callAdapter对象是在createCallAdapter()方法里返回的,如下

 private CallAdapter createCallAdapter() {
      
      //1.获取该方法的返回类型
      Type returnType = method.getGenericReturnType();
     
     //2.校验该返回类型是否可处理
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      
       //3.判断是void类型
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter) 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);
      }
    }

继续往下看

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 = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

可以看出CallAdapter主要是由Retrofit里的nextCallAdapter方法生成,从adapterFactories集合中取出一个factory然后调用get方法生成。一开始我们就讲到这个factory如果不自定义的话就是默认自带的ExecutorCallAdapterFactory类,在这里我们看看具体类,

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

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

      @Override public Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };

   ............
  }
 
  

可以看出这里返回了一个匿名类,两个方法,一个是responseType获取请求响应类型,一个是adapt方法,这个adapt方法返回了一个Call对象,具体实现类是ExecutorCallbackCall,我们看下这个类,,,,,等等

通过Retrofit2来看http_第3张图片
咋又出现一个ExecutorCallbackCall类,这类干嘛的,有点懵逼,,,,也有点营养不良

通过Retrofit2来看http_第4张图片

这里有点绕,博主看代码的时候,看到这里经常找不到北,赶紧回到主线,一步一步来

return serviceMethod.callAdapter.adapt(okHttpCall);

我们已经知道 在不自定义的情况下,callserviceMethod.callAdapter获取到的是一个匿名的callAdapter,执行adapt方法,返回了ExecutorCallbackCall对象,这时候再看这个类,

static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

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

    @Override public void enqueue(final Callback callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                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);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }

回过头来,终于知道了这个repos对象具体实现就是ExecutorCallbackCall对象

Call> repos = service.listRepos("octocat");

继续往下走通过Call对象去请求,即调用enqueue方法,我们看看这个方法,

@Override public void enqueue(final Callback callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

这个 delegate就是OkHttpCall对象,不清楚的可以回顾下上面讲的,执行OkHttpCall
的eneque方法,还记不记得上面讲过OkHttpCall 两个重要的方法,现在我们看看OkHttpCall的eneque方法

 @Override public void enqueue(final Callback 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 {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

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

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

    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response 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 response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

到这里相信眼睛锐利的网友们可以已经察觉真相,慢慢浮出水面了。。
在这里new了一个okhttp3.Call,并且执行okhttp3.Call的enqueue方法,鼓掌。。。
通过Retrofit2来看http_第5张图片
还没完,我们再看看如何生成okhttp3.Call对象的,

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

是不是很眼熟,之前讲ServiceMethod类的时候提到过这个方法toReques(),最初转换成
Okhttp里的Request对象,然后通过Request对象newCall一个Call对象,我们看下这个newCall方法,

  interface Factory {
    Call newCall(Request request);
  }

是个接口,我们看下具体实现,

 @Override 
 public Call newCall(Request request) {
  return RealCall.newRealCall(this, request, false /* for web socket */);
 }

熟悉okhttp的同学是不是一看就明白了,
通过Retrofit2来看http_第6张图片

还没完,请求看完了,响应呢,我们看看parseResponse方法,

Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      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;
    }
  }

又看到了一个熟悉的背影,serviceMethod.toResponse(catchingBody),看下具体实现

 /** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

可以看出ServiceMethod对象将ResponseBody对象转换成用户定义的类型对象,其中 responseConverter来自Retrofit对象中的converterFactories集合,

 public  Converter nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter) converter;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
        .append(type)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

同样如果用户没有定义会有一个默认的转换工具BuiltInConverters,responseBodyConverter方法将ResponseBody对象转换成用户定义的类型对象

final class BuiltInConverters extends Converter.Factory {
  @Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }
.........
}

回到主线来,快接近尾声了,parseResponse方法返回后,执行callSuccess方法,

 private void callSuccess(Response response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

注意这里的callback并不是用户自定义的callback,而是OkhttpCall的execute方法的入参,执行 callback.onResponse(OkHttpCall.this, response),callbackExecutor将异步任务结果抛到主线程中去,然后这里的callback就是我们一开始repos.enqueue方法传进来的回调,会在主线中执行。

delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                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);
            }
          });
        }
      });

到这里就算读完整个Retrofit框架流程了,其实还有很多细节,在这里就不一一讲了。
另外,作为一名技术人员,一定要做到知其然知其所以然。

  • 总结

1.对于一个框架使用,要清晰的知道它是干嘛的。
2.了解它的使用方式,了解它的常用的api
3.研究源码,设计流程和结构。

Thanks~*

你可能感兴趣的:(android)