retrofit2.5.0源码分析

简介

Retrofit是目前比较流行的网络框架,它是以restful风格的请求方式,将接口请求使用动态代理方式将获取方法名,方法注解,方法参数注解,方法值翻译成http请求,内部封装了以okhttp作为底层的网络请求框架。除此之外有强大可扩展型,以及返回结果支持各种格式转换,以及对rxjava的支持。

gradle引用

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
//rxjava
api 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
//数据转换
api 'com.squareup.retrofit2:converter-gson:2.5.0'
//过滤器
api 'com.squareup.okhttp3:logging-interceptor:3.8.0'

github地址https://github.com/square/retrofit

使用

官方使用说明http://square.github.io/retrofit/

首先创建api接口

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

获取动态代理对象

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

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

创建Call对象

   Call<Repo> call = gitHubService.listRepos("");

执行异步网络请求

call.enqueue(new Callback<Repo>() {
       @Override
       public void onResponse(Call<Repo> call, Response<Repo> response) {

       }

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

       }
   });

问题

源码解析

 Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

首先retrofit通过一个Builder模式,创建一个retrofit实例。

 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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

  // Make a defensive copy of the converters.
  List<Converter.Factory> converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

  // Add the built-in converter factory first. This prevents overriding its behavior but also
  // ensures correct behavior when using converters that consume all types.
  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());

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

通过build方法进行属性校验并初始化一些变量。

 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();
      private final Object[] emptyArgs = new Object[0];

      @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);
        }
        return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
      }
    });
}

然后通过creat创建一个接口实例,creat主要通过Proxy.newProxyInstance方法创建一个动态代理。在newProxyInstance的invoke方法中method可以拿到接口的方法名;方法的注解类型,以及接口方法的注解的key值,以及注解的value值。

 GitHubService gitHubService=(GitHubService) Proxy.newProxyInstance(GitHubService.class.getClassLoader(),
            new Class[]{GitHubService.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("方法名"+method.getName());
                    GET get = method.getAnnotation(GET.class);
                    System.out.println("方法的注解值"+get.value());
                    Annotation[] annotations = method.getAnnotations();
                    for (int i = 0; i <annotations.length ; i++) {
                        System.out.println("方法参数的注解"+Arrays.toString(annotations));
                    }
                   System.out.println("方法的参数值"+Arrays.toString(args));
                    return null;
                }
            });
    gitHubService.listRepos("111");

通过代理获取method相关的一些信息

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

synchronized (serviceMethodCache) {
  result = serviceMethodCache.get(method);
  if (result == null) {
    result = ServiceMethod.parseAnnotations(this, method);
    serviceMethodCache.put(method, result);
  }
}
return result;
}

loadServiceMethod方法返回ServiceMethod对象。如果有缓存就从缓存中取,如果没有直接创建一个放map中。ServiceMethod通过 result = ServiceMethod.parseAnnotations(this, method)获取。

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
  throw methodError(method,
      "Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
  throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}



   static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
  Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
  throw methodError(method, "'"
      + Utils.getRawType(responseType).getName()
      + "' is not a valid response body type. Did you mean ResponseBody?");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
  throw methodError(method, "HEAD method must use Void as response type.");
}

Converter<ResponseBody, ResponseT> responseConverter =
    createResponseConverter(retrofit, method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}

ServiceMethod是一个抽象类,调用的是它子类HttpServiceMethod的parseAnnotations方法,在该方法中直接new HttpServiceMethod对象。

 private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
  CallAdapter<ResponseT, ReturnT> callAdapter,
  Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}

HttpServiceMethod类中的相关属性和方法。

return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

回到creat方法,最后调用的是invoke方法。

扫描二维码关注公众号,回复: 6488011 查看本文章
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
    new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

invoke的具体实现,该方法就会返回一个Call对象,allAdapter.adapt()方法就是将OkHttpCall对象转换成其他平台能用的Call对象,比如:RxJava。这里返回的是OkHttpCall的对象,该类是Retrofit中定义的,是对Okhttp中的Call对象的封装。

OkHttpCall(RequestFactory requestFactory, Object[] args,
  okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}

……
……

 @Override public synchronized Request request() {
okhttp3.Call call = rawCall;
if (call != null) {
  return call.request();
}
if (creationFailure != null) {
  if (creationFailure instanceof IOException) {
    throw new RuntimeException("Unable to create request.", creationFailure);
  } else if (creationFailure instanceof RuntimeException) {
    throw (RuntimeException) creationFailure;
  } else {
    throw (Error) creationFailure;
  }
}
try {
  return (rawCall = createRawCall()).request();
} catch (RuntimeException | Error e) {
  throwIfFatal(e); // Do not assign a fatal error to creationFailure.
  creationFailure = e;
  throw e;
} catch (IOException e) {
  creationFailure = e;
  throw new RuntimeException("Unable to create request.", e);
}
}

@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) {
      throwIfFatal(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) {
    Response<T> response;
    try {
      response = parseResponse(rawResponse);
    } catch (Throwable e) {
      throwIfFatal(e);
      callFailure(e);
      return;
    }

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

  @Override public void onFailure(okhttp3.Call call, IOException e) {
    callFailure(e);
  }

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

以上是OkHttpCall对象部分代码,其实内部主要是调用okhttp3的call对象的网络同步或者异步请求等。

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

通过requestFactory的create方法创建了okhttp3.Call对象。

final class RequestFactory {

  ………………

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

………………

okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

int argumentCount = args.length;
if (argumentCount != handlers.length) {
  throw new IllegalArgumentException("Argument count (" + argumentCount
      + ") doesn't match expected count (" + handlers.length + ")");
}

RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
    headers, contentType, hasBody, isFormEncoded, isMultipart);

List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
  argumentList.add(args[p]);
  handlers[p].apply(requestBuilder, args[p]);
}

return requestBuilder.get()
    .tag(Invocation.class, new Invocation(method, argumentList))
    .build();
}
}

在RequestFactory类中可以看出该方法就是根据ParameterHandler解析的参数以及传入的参数值args创建Request对象.

总结

调用Retrofit.creat方法创建接口实例。内部使用动态代理,ServiceMethod调用invoke方法,ServiceMethod是抽象类,实际是它的子类HttpServiceMethod
调用。HttpServiceMethod是对请求方法的封装,主要有requestFactory、callFactory、callAdapter、responseConverter成员变量。

转载于:https://www.jianshu.com/p/4d911c76e320

猜你喜欢

转载自blog.csdn.net/weixin_34376562/article/details/91225609