一个Demo让你理解Retrofit的工作原理-动态代理技术

首先先总结下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的原理就清晰的多了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/fagawee/article/details/103954430