一、简介
1、Retrofit是基于RESTful风格的http网络请求框架封装
2、Retrofit是基于OKHttp
3、可以配置不同HTTP client来实现网络请求,如okhttp、httpclient等
4、将接口的定义与使用分离开来,实现好的分工。
5、支持多种返回数据解析的Converter可以快速进行数据转换。
6、和RxJava集成的很好,因为容易和RxJava结合使用,所以对于异步请求,同步请求也不需要做额外的工作。
二、简单的使用
1、定义一个 接口文件
@GET("/blog/page/{page}")
fun getBlogList(@Path("page") page:Int):Call<Any>
2、创建Retrofit对象
val retrofit = Retrofit.Builder()
.baseUrl("http://www.matrix67.com/")
.addConverterFactory(GsonConverterFactory.create())
//.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
这里用到了建造者模式和工厂模式
3、请求网络
val mineService = retrofit.create(MineService::class.java)
val call = mineService.getBlogList(1)
val executeResponse = call.execute() //同步方式
call.enqueue(object :Callback<Any>{ //异步方式
override fun onResponse(call: Call<Any>, response: Response<Any>) {
TODO("Not yet implemented")
}
override fun onFailure(call: Call<Any>, t: Throwable) {
TODO("Not yet implemented")
}
})
execute是同步方式,enqueue是异步方式
三、核心源码
这里核心是探讨Retrofit是怎么把一个接口 方法最后转成可以执行网络请求的Call,主要是 retrofit.create这个方法
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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, @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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
我们来逐行阅读:
1、验证service是不是一个接口文件
Utils.validateServiceInterface(service);
看具体实现,可以看到第一个验证是否是接口,不是抛异常,第二个验证是否是唯一接口,没有继承其它接口,如果有继承其他接口会抛异常。
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
2、是否开启更早的校验,这里如果开启了,就会校验service中方法定义,包括注解,是否合法。实际开发中,测试可以开启,上线后别开启了,会消耗性能。
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
再来看看 Platform.get()方法,这里会找到对应的平台,Android和Java8,这里我们是Android
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();
}
我们再来看看循环里面做了什么,拿出service中定义的方法,如果不是平台默认的方法,就执行loadServiceMethod
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
再来看看 loadServiceMethod方法,可以看到 第三方部 build会校验method相关信息,这个就不细致讨论了,知道是个校验功能就行了。
//1、Retrofit文件
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;
}
//2、ServiceMethod文件中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(); //方法参数的注解
}
//3、new ServiceMethod.Builder<>(this, method).build();
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
3、返回一个动态代理构造的接口实现类对象
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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
这个动态代理是整个Retrofit最核心部分,动态代理模式是属于代理模式的一种
先简单介绍下代理模式
(1)静态代理:在代码运行之前就已经固定好了委托对象和代理对象,且在代码编译之后将不可更改。
举例:我想买件商品,我委托代购帮买,我自己就是委托对象。
代码示例:
public interface Goods{
void buy();
}
public class Delegate implements Goods{
@Override
public void buy() {
}
}
public class Proxy implements Goods{
Delegate delegate;
Proxy(){
delegate = new Delegate();
}
@Override
public void buy() {
delegate.buy();
}
}
优点:
1、隐藏委托类的具体实现。
2、实现客户与委托类的解耦,在不改变委托类代码的情况下添加一些额外的功能(日志、权限)等。
缺点:
1、当需要代理多个类时,代理对象要实现与目标对象一致的接口。要么,只维护一个代理类来实现多个接口,但这样会导致代理类过于庞大。要么,新建多个代理类,但这样会产生过多的代理类。
2、当接口需要增加、删除、修改方法时,目标对象与代理类都要同时修改,不易维护。
于是,动态代理便派上用场了。
(2)动态代理:在程序运行时委托对象可以动态设置给代理对象。
这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
实现动态代理通常有两种方式:JDK原生动态代理和CGLIB动态代理。
这里用到JDK的,主要用到Proxy和InvocationHandler两个类
我们点击Retrofit中的newProxyInstance方法:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// Android-removed: SecurityManager calls
/*
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
*/
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// Android-removed: SecurityManager / permission checks.
/*
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
// BEGIN Android-removed: Excluded AccessController.doPrivileged call.
/*
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
*/
cons.setAccessible(true);
// END Android-removed: Excluded AccessController.doPrivileged call.
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
我们发现通过 getProxyClass0 得到一个Proxy代理类,然后这个类得到构造方法,然后构造方法传递h,cons.newInstance(new Object[]{h});这样来得到实例对象。
这个类我们可以通过反编译手段得到,这个实例对象实际上是继承了 Proxy类,同时实现了 对应service接口 。
然后通过动态代理得到的实例对象,调用方法时都会调用 super().h.invoke,而这个h是通过Proxy的构造方法传递进来的。
// Android-added: Helper method invoke(Proxy, Method, Object[]) for ART native code.
private static Object invoke(Proxy proxy, Method method, Object[] args) throws Throwable {
InvocationHandler h = proxy.h;
return h.invoke(proxy, method, args);
}
这里java代码有辅助类实现这一功能
我们看下 getProxyClass0具体实现
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
再来看看 proxyClassCache
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
WeakCache 中有分段锁Map结构
这个不用管,就是一个缓存结构
再来看看 ProxyClassFactory() 这个工厂作用生产Proxy实例对象
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use the default package.
proxyPkg = "";
}
{
// Android-changed: Generate the proxy directly instead of calling
// through to ProxyGenerator.
List<Method> methods = getMethods(interfaces);
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
validateReturnTypes(methods);
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
return generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
}
}
再来看看最后一行发现是一个native方法,辅助Proxy中的invoke方法实现一个 继承Proxy,并实现service接口的类。
@FastNative
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
ClassLoader loader, Method[] methods,
Class<?>[][] exceptions);
具体 看生成了Proxy0,需要自己反编译看,可以看这个文章:
4、InvocationHandler对象 invoke方法回调具体代码
// 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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
(1)判断method是否是Object声明的,如果是Object声明的,比如 toString等方法,直接调用 method.invoke(this, args);
(2)判断method是否是平台默认方法,是就调用平台默认方法
(3)后面的三行代码才是Retorfit整个库最核心的部分,把接口中的方法转成实现service的 Object对象,这个对象可以执行网络请求。
5、ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
主要功能是对接口方法 的解析,包括参数 和 返回值
6、OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
生成一个可以用于Okhttp请求的Call
7、serviceMethod.adapt(okHttpCall);
主要用于网络请求结束后切换到主线程,还有就是和Rxjava适配器转换,由Rxjava去进行线程切换
四、其他不重要源码分析
可以参照其他文章:https://www.jianshu.com/p/0c055ad46b6c