美文网首页
retrofit2源码分析(一)

retrofit2源码分析(一)

作者: nothingren | 来源:发表于2017-05-14 20:29 被阅读0次

先从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");
            }
        });

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的事情了,具体可以参考Okhttp相关文章。

相关文章

网友评论

      本文标题:retrofit2源码分析(一)

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