retrofit2源码分析

来源:互联网 发布:南宁三中教师待遇知乎 编辑:程序博客网 时间:2024/06/01 23:02

先从Retrofit的使用开始介绍。一个简单的使用例子如下:

    Retrofit retrofit = new Retrofit.Builder()                .baseUrl("http://172.18.157.142:8080")                //.addConverterFactory(GsonConverterFactory.create())                .build();        TestApi testApi = retrofit.create(TestApi.class);        Map<String,String> p = new HashMap<>();        p.put("key","123");        Call<ResponseBody> userCall = testApi.getTestResult("/user/nothing",p);        userCall.enqueue(new Callback<ResponseBody>() {            @Override            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {            }            @Override            public void onFailure(Call<ResponseBody> call, Throwable t) {                System.out.println("================onFailure");            }        });

okhttp使用例子:

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();
client.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
            e.printStackTrace();
      }
      @Override
      public void onResponse(Call call, Response response) throws IOException {
      }
});

下面看他们是如何联系的(retrofit是基于okhttp3封装的)

TestApi的源码入下:

interface TestApi {    @GET("{path}")    Call<ResponseBody> getTestResult(@Path("path") String path, @QueryMap(encoded = true)Map<String,String> options);}

Retrofit的使用步骤还是比较麻烦的,主要有如下步骤:
1 创建一个Retrofit实例
2 根据具体的网络请求,创建一个接口,此接口的方法主要用于传入url和参数。
3 根据第二步创建的接口,获取一个Call。
4 调用Call的异步方法enqueue获取返回数据。

下面就从源码的角度详细分析Retrofit的原理。
先从第一步的build()方法开始,build()方法源码如下:

public Retrofit build() {      if (baseUrl == null) {        throw new IllegalStateException("Base URL required.");      }      okhttp3.Call.Factory callFactory = this.callFactory;      if (callFactory == null) {        callFactory = new OkHttpClient();//默认的Factory,可配置      }      Executor callbackExecutor = this.callbackExecutor;//返回回调的线程      if (callbackExecutor == null) {        callbackExecutor = platform.defaultCallbackExecutor();//默认是主线程      }      // Make a defensive copy of the adapters and add the default Call adapter.      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));      // Make a defensive copy of the converters.      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,          callbackExecutor, validateEagerly);    }

接下来看Retrofit的create()方法,源码如下:

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, Object[] args)              throws Throwable {            // If the method is a method from Object then defer to normal invocation.            if (method.getDeclaringClass() == Object.class) {//Object的相关方法不能被代理              return method.invoke(this, args);            }            if (platform.isDefaultMethod(method)) {//可以不用管,java里面用到,android平台默认为false              return platform.invokeDefaultMethod(method, service, proxy, args);            }            ServiceMethod<Object, Object> serviceMethod =                (ServiceMethod<Object, Object>) loadServiceMethod(method);//获取ServiceMethod            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//创建OkHttpCall            return serviceMethod.callAdapter.adapt(okHttpCall);//动态代理的拦截执行          }        });  }

create()方法返回了一个动态代理,从create()方法也可以看出,其参数service必须是一个接口,这个是动态代理的机制决定,有关动态代理相关知识,请自行百度。
Method的getDeclaringClass()方法返回Method定义所在的类。
动态代理最后调用了ServiceMethod的CallAdapter的adapt()方法。
ServiceMethod的CallAdapter是怎么初始化的呢?还需要从loadServiceMethod()这个方法说起。loadServiceMethod()源码如下:

  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();//如果result中没有满足需求的ServiceMethod,就创建一个        serviceMethodCache.put(method, result);      }    }    return result;  }

ServiceMethod.Builder的build()方法源码如下:

    public ServiceMethod build() {      callAdapter = createCallAdapter();//创建CallAdapter      …...      return new ServiceMethod<>(this);    }

createCallAdapter()方法源码如下:

    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.");      }      Annotation[] annotations = method.getAnnotations();      try {        //noinspection unchecked        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);//从Retrofit中获取。      } catch (RuntimeException e) { // Wide exception range because factories are user code.        throw methodError(e, "Unable to create call adapter for %s", returnType);      }    }

Retrofit的callAdapter()源码如下:

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {    return nextCallAdapter(null, returnType, annotations);  }  public CallAdapter<?, ?> nextCallAdapter(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.Factory,调用其get()方法,如果不为空,则返回。      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());  }

adapterFactories.get()获取的CallAdapter.Factory其实就是Retrofit的Build在调用build()方法的时候设置的。先看Platform的源码:

    static class Android extends Platform {        @Override        public Executor defaultCallbackExecutor() {            return new MainThreadExecutor();        }        @Override        CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {            return new ExecutorCallAdapterFactory(callbackExecutor);//Retrofit使用的就是这个Factory        }        static class MainThreadExecutor implements Executor {            private final Handler handler = new Handler(Looper.getMainLooper());            @Override            public void execute(Runnable r) {                handler.post(r);            }        }    }

所以adapterFactories.get()获取的就是ExecutorCallAdapterFactory。ExecutorCallAdapterFactory的get()方法源码如下:

  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<Object, Call<?>>() {      @Override public Type responseType() {        return responseType;      }      @Override public Call<Object> adapt(Call<Object> call) {        return new ExecutorCallbackCall<>(callbackExecutor, call);      }    };  }

先看if里面的判断条件,returnType的获取方式为:

method.getGenericReturnType()

Method的getGenericReturnType()返回的就是Method的返回值类型,比如:void,int,String等。而在这里代表的是文章开头描述的第二步中的接口中的方法返回值。如果不是Call的话,if会返回false,否则返回一个CallAdapter。
CallAdapter的adapt()方法返回的是一个ExecutorCallbackCall的实例。
也就是说Retrofit的create()方法的动态代理最终返回了一个ExecutorCallbackCall实例。
对应到开头的例子中,也就是

  TestApi testApi = retrofit.create(TestApi.class);//获取的是一个代理类,而不是new出来的。  Call<ResponseBody> userCall = testApi.getTestResult("/user/renyiguang",p);//获取到的是ExecutorCallbackCall的实例。

所以在调用userCall.enqueue()方法时,其实是调用的ExecutorCallbackCall的enqueue()方法。ExecutorCallbackCall源码如下:

static final class ExecutorCallbackCall<T> implements Call<T> {    final Executor callbackExecutor;    final Call<T> delegate;    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {      this.callbackExecutor = callbackExecutor;      this.delegate = delegate;    }    @Override public void enqueue(final Callback<T> callback) {      checkNotNull(callback, "callback == null");      delegate.enqueue(new Callback<T>() {        @Override public void onResponse(Call<T> call, final Response<T> 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<T> 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<T> 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<T> clone() {      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());    }    @Override public Request request() {      return delegate.request();    }  }

ExecutorCallbackCall其实是个代理类,其方法都是调用的delegate的相应方法。delegate是什么呢?是CallAdapter调用adapt()传入的参数。CallAdapter的adapt()是何时调用的呢?还是在Retrofit的create()中,传入的是OkHttpCall。
那么就看一下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 {          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<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();        }      }    });  }

这个方法可以说是retrofit真正的入口方法。先来看一下createRawCall()这个方法。

  private okhttp3.Call createRawCall() throws IOException {    Request request = serviceMethod.toRequest(args);//根据输入参数返回Request。这是OkHttp的Request    okhttp3.Call call = serviceMethod.callFactory.newCall(request);//根据request,返回call,这是OkHttp的call。    if (call == null) {      throw new NullPointerException("Call.Factory returned null.");    }    return call;  }

ServiceMethod的toRequest()方法实现如下:

  Request toRequest(Object... args) throws IOException {    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,        contentType, hasBody, isFormEncoded, isMultipart);    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;    int argumentCount = args != null ? args.length : 0;    if (argumentCount != handlers.length) {      throw new IllegalArgumentException("Argument count (" + argumentCount          + ") doesn't match expected count (" + handlers.length + ")");    }    for (int p = 0; p < argumentCount; p++) {      handlers[p].apply(requestBuilder, args[p]);//这里是参数参数配置的核心,具体细节下一节会专门分析    }    return requestBuilder.build();  }

当拿到Okhttp的Request之后就是Okhttp的事情了。