首先先总结下Retrofit核心的三个技术
1. java的动态代理技术:
2. 解析定义的Service中的各种注解,生成request,然后利用okhttp,生成response
3. 利用各种设计模式,尤其是工厂模式,来适配Rxjava 还有动态配置Gson 结果转换器
Retrofit 总结起来不外乎就这三点,我们今天只通过一个Demo 分析Retrofit中的动态代理,我后面的文章来分析其他的部分
首先我们知道Retrofit 在使用的时候是要写Service的就像这样
@FormUrlEncoded
@POST("/api/user/deviceValidate")
Observable<DeviceValidateNetBean> deviceValidate(@Field("did")String did, @Field("flat_mac")String flat_mac);
这里我们只是模拟,所以就写个简单的Service,但是原理都是一样的
public interface MyService {
ResModel get(String url);
ResModel post(String url);
}
public class ResModel {
public String url;
public String result;
}
我们看到除了没有注解,其他都是一个原理,一个interface就可以,注解的解析不是今天讨论的
下面是java动态代理技术的核心代码
MyService service=(MyService)Proxy.newProxyInstance(MyService.class.getClassLoader(), new Class<?>[]{MyService.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name=method.getName();
String url=(String) args[0];
if(name.equals("get"))
{
ResModel resModel=new ResModel();
resModel.result="get返回值";
resModel.url="返回的"+url;
return resModel;
}
else if(name.equals("post"))
{
ResModel resModel=new ResModel();
resModel.result="post返回值";
resModel.url="返回的"+url;
return resModel;
}
else
{
return null;
}
// return null;
}
});
ResModel resModel_get=service.get("geturl");
ResModel resModel_post=service.post("posturl");
Log.i("Test",resModel_get.result+" "+resModel_get.url);
Log.i("Test",resModel_post.result+" "+resModel_post.url);
结果:
01-13 11:10:02.501 10538-10538/com.fagawee.fmvp.app I/Test: get返回值 返回的geturl
01-13 11:10:02.502 10538-10538/com.fagawee.fmvp.app I/Test: post返回值 返回的posturl
我们看到结果完全符合预期
在Retrofit里面也是通过
Service serivce=Retrofit.create(Service.class);
serivce.get(url)
来使用的,我们上面那个Demo也传入了MyService,然后 Proxy.newProxyInstance 一个代理对象,然后请求方法,完成请求的
接下来我们看下动态代理是如何使用的,
1、Proxy 这个是java中的动态代理的对象生产者,可以实例化一个动态代理对象,记住这个实例化出来的动态代理对象不是真的被代理的对象,是代理者,只不过里面的方法和真的对象一致,在上面那个例子中,通过Debug,我们可以看到MyService 这个对象是个xxx.xxx.Proxy5.class 的对象
2、newProxyInstance这个方法传入三个参数
1、要代理对象的ClassLoader对象,这个 可以通过对象的Class类的getClassLoader获取
2、要代理的对象的接口Class类型的数组,上面的例子就传入了,new Class<?>[]{MyService.class}
3、InvocationHandler回调方法,这个回调方法是必须实现的,其作用就是当代理对象的方法被调用的时候,可以在这个回调方法中被回调,并且返回对应的值,
这个回调方法有3个参数:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy是真实的代理对象,method,是代理对象调用方法的反射方法,args是对应方法的参数,
返回值是Object,这个是方法的返回值
上面这个Demo虽然很简单,Retrofit里面代码很多,逻辑复杂,但是生成Service的原理上都是一致的,只不过
它在
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name=method.getName();
String url=(String) args[0];
if(name.equals("get"))
{
ResModel resModel=new ResModel();
resModel.result="get返回值";
resModel.url="返回的"+url;
return resModel;
}
else if(name.equals("post"))
{
ResModel resModel=new ResModel();
resModel.result="post返回值";
resModel.url="返回的"+url;
return resModel;
}
else
{
return null;
}
// return null;
}
这一步做了大量的注解解析,还有大量的设计模式,使整个框架松耦合,高可配置,
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.callAdapter.adapt(okHttpCall);
}
});
}
上面这段代码就是Retrofit在create Service的核心代码, 可以看出是java的动态代理技术来生成代理service的,里面的
ServiceMethod:负责注解的解析工作,最后转成Request,和Response
OkHttpCall:通过Okhttp来完成具体的请求工作
callAdapter:这个就是Rxjava的Adapter适配(主流),Retrofit 也提供了默认的callAdapter
这么一看Retrofit的原理就清晰的多了