Retrofit使用及解析(二)

目录

1.代理模式

1)静态代理

2)动态代理-jdk方式

3)动态代理-CGLIB

2.retrofit源码

1)Retrofit类变量

2)链式调用-Retrofit.builder()

3)链式调用-baseUrl()

4)链式调用-addConverterFactory()

5)链式调用-addCallAdapterFactory

5)链式调用-build()


1.代理模式

public interface Api {
    @GET("...")
    Call<Object> getSearch(@QueryMap Map<String, String> options);
}

我们请求的url都是完整的路径,类似http://XX.XX.XX?name=xx,但是我们使用Retrofit时,并未看见。Retrofit使用的动态代理,自动的将我们接口类中的参数和基础网络路径拼接成最后的请求路径

什么是动态代理:为其他对象提供代理,用以控制整个对象的访问。(通俗就是你找代购海外买东西,不用关心别人采购或者怎么带回国的细节,只需要关心你最终拿到东西)。

1)静态代理

三个角色:

a.抽象对象角色:声明目标类和代理类都要继承的公共接口

public abstract class AbstractObject {
    protected abstract void doThing();
}

b.目标对象角色:比如我想买个什么东西

public class RealObject extends AbstractObject {
    @Override
    protected void doThing() {
    }
}

c.代理对象角色:

public class ProxyObject extends AbstractObject {

    private RealObject realObject;

    public ProxyObject(RealObject realObject){
        this.realObject=realObject;
    }

    @Override
    protected void doThing() {
        Log.e("--", "before doThing");
        if(realObject==null){
            realObject = new RealObject();
        }
        realObject.doThing();
        Log.e("--", "after doThing");
    }
}

好处就是:(利于功能划分)不修改原实现的抽象函数,将自己的代码逻辑穿插前后,使得代码维护性变高。

2)动态代理-jdk方式

动态代理优点:无侵入式扩展代码:在程序运行时,且不修改源代码情况下,动态生成代码添加至程序。

原理:辅助接口,通过反射机制生成类的形式,插入自己逻辑

限制:只能为接口创建代理

看demo,先定义接口,表达的是代理类和被代理类都要执行的操作:

public interface Subject {
    void doThing();
}

创建被代理类,实现接口:

public class People implements Subject {
    @Override
    public void doThing() {
        Log.e("--", "do thing");
    }
}

创建代理类:

public class Proxy implements InvocationHandler {

    private Object target;

    public Proxy(Subject target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.e("--", "proxy: "+proxy.getClass().getName());
        Log.e("--", "before");
        method.invoke(target, args);
        Log.e("--", "after");
        return null;
    }
}

 先看看InvocationHandler,每一个动态代理类(Proxy)的调用处理程序都必须实现InvocationHandler接口,并且每个被代理类的实例(Prople)都关联到了实现该接口的动态代理类调用处理的程序中:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用

第一个参数:Object proxy  ->  目标对象的代理

第二个参数:Method method  ->  目标对象的方法

第三个参数:Object[] args  ->  指代目标对象某个方法的所有参数

总结:每个代理类Proxy中,都包含一个对象,关联内部处理逻辑的InvocationHandler接口的实现。当调用代理对象接口中方法时候,调用信息传到invoke方法,可以从参数获取到代理对象、方法、方法参数,最终将返回值返回出去,起到类似拦截的作用。

测试动态代理:

//被代理类
Subject people = new People();
//代理类
Proxy proxy = new Proxy(people);
//反射获取目标对象的代理对象     newProxyInstanc作用生成代理类
Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(
                people.getClass().getClassLoader(),
                people.getClass().getInterfaces(),
                proxy);

 看看java.lang.reflect.Proxy:

public class Proxy implements java.io.Serializable {

    ...
    protected InvocationHandler h;

    protected Proxy(InvocationHandler h) {
        this.h = h;
    }
}

类中构造方法传入参数InvocationHandler给全局变量,实现两者关联。

再看看newProxyInstance:

//ClassLoader 将动态生成代理类的字节码文件加载到jvm
//Class<?>[]  被代理类实现的接口
//InvocationHandler 代理对象调用方法时候,关联到InvocationHandler的invoke
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
       ...
    }

3)动态代理-CGLIB

原理:修改字节码

参考:https://www.cnblogs.com/yangming1996/p/6824249.html

2.retrofit源码

new Retrofit.Builder()
                .baseUrl(...)
                .addCallAdapterFactory(...)
                .addConverterFactory(...)
                .build();

上面的初始化应该很熟悉了,看看Retrofit类:

1)Retrofit类变量

public final class Retrofit {

// Method-请求方法    ServiceMethod-网络请求接口中的方法注解后,并解析后的对象  
//2个成对出现  ->作用存储请求配置,请求方法,数据转换器,网络请求适配器等
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
//工厂模式  -> 生产okhttpclient
private final okhttp3.Call.Factory callFactory;
//请求基础路径  与接口类中相对地址拼接成完整请求地址
private final HttpUrl baseUrl;
//数据转换器工厂的集合  数据response的转换,变成java对象
private final List<Converter.Factory> converterFactories;
//网络请求适配器工厂集合  将call转化成其他平台的类型  比如rxjava
private final List<CallAdapter.Factory> adapterFactories;
//执行相关回调
private final Executor callbackExecutor;
//是否需要立即解析接口中的方法
private final boolean validateEagerly;

...
}

2)链式调用-Retrofit.builder()

public final class Retrofit {

    ...

 public static final class Builder {
    
    //适配的平台
    private Platform platform;
    //网络请求工厂 默认使用okhttp请求
    private okhttp3.Call.Factory callFactory;
    //HttpUrl类型的请求类型,由string转化而来
    private HttpUrl baseUrl;
    //数据转换器集合   转换response的
    private List<Converter.Factory> converterFactories = new ArrayList<>();
    //网络请求适配器工厂的集合 
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    //异步回调的执行器   切换线程用的
    private Executor callbackExecutor;
    //是否立即解析接口中的方法或者注解参数等
    private boolean validateEagerly;

    。。。
    Builder(Platform platform) {
      //平台对象赋值
      this.platform = platform;
      //数据转换器工厂添加BuiltInConverters默认转换器工厂
      converterFactories.add(new BuiltInConverters());
    }

    public Builder() {
      this(Platform.get());
    }

   。。。
}

    ...
}

和Retrofit的成员变量很类似。看下有参构造的参数Platform.get(),发现最终调用:

private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");//反射
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();  //返回android平台
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");//反射
      return new Java8();        //返回Java8平台
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");//反射
      return new IOS();        //返回IOS平台
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

再看看我们Android():

static class Android extends Platform {

    //返回MainThreadExecutor默认的回调方法执行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    //创建默认网络适配器工厂  
    //产生的calladapter,让call请求在异步调用时指定Executor执行器,来执行回调
    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    
    static class MainThreadExecutor implements Executor {
      //MainThreadExecutor绑定了主线程的looper,通过handler通信,方便线程切换
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

总结:builder()方法做了平台判定,添加默认数据转换器等操作

3)链式调用-baseUrl()

public Builder baseUrl(String baseUrl) {
      //判断是否为空
      checkNotNull(baseUrl, "baseUrl == null");
      //string类型url转成HttpUrl类型
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      //返回处理后的值
      return baseUrl(httpUrl);
}

看下baseUrl(httpUrl):

    public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
       //将baseUrl拆分成多部分
      List<String> pathSegments = baseUrl.pathSegments();
        //末尾部分必须以'/'结尾
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

总结:就是string类型url转成HttpUrl类型,即转换成okhttp请求可识别的请求类型

4)链式调用-addConverterFactory()

比如调用如下:

new Retrofit.Builder()
                .baseUrl("XXXXX")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    public Builder addConverterFactory(Converter.Factory factory) {
      //将数据转换器加入到集合
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

只是做了添加操作,再看看GsonConverterFactory.create():

public final class GsonConverterFactory extends Converter.Factory {
 
  private final Gson gson;

  //第一步:调用无参
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  //第二步:内部调用有参
  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

  //第三步:初始化的gson给全局变量
  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }

    ...
}

总结:将初始化gson的转化器添加(默认使用gson解析)

对应依赖包:

compile 'com.squareup.okhttp3:okhttp:3.1.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

5)链式调用-addCallAdapterFactory

new Retrofit.Builder()
                .baseUrl("XXXXX")
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      //加入集合操作
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

也是做了加入集合操作,再看看RxJavaCallAdapterFactory.create():

public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {

  //第一步:初始化有参构造
  public static RxJavaCallAdapterFactory create() {
    return new RxJavaCallAdapterFactory(null);
  }

  //第二步:Rxjava调度器Scheduler的赋值
  private final Scheduler scheduler;
  private RxJavaCallAdapterFactory(Scheduler scheduler) {
    this.scheduler = scheduler;
  }

  //必须传入非空的scheduler 
  public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
    if (scheduler == null) throw new NullPointerException("scheduler == null");
    return new RxJavaCallAdapterFactory(scheduler);
  }

    。。。
}

看到create()只是将null赋值给全局调度器变量Scheduler 。

依赖包:

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

补充RxJavaCallAdapterFactory:

RxJavaCallAdapterFactory extends CallAdapter.Factory

看看CallAdapter:

public interface CallAdapter<T> {
    
    //返回http解析后的类型,即retrofit接口类中call泛型参数的类型,如call<User>,即user类
    Type responseType();

    //T指代需要转换成接口的返回类型,Call就是传入的okhttpcall实例
    //如是rxjava,T则对应rxjava当中的类型,扩展性强 
    <R> T adapt(Call<R> call);
    
    //内部类Factory 
    abstract class Factory {
        
        //根据接口返回的类型得到实际需要的calladapter
        public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

        //主要返回index泛型参数的上限
        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
          return Utils.getParameterUpperBound(index, type);
        }

        //获取原始的类型->决定后面判断选择不同的calladapter
        protected static Class<?> getRawType(Type type) {
          return Utils.getRawType(type);
        }
    }
}

CallAdapter的作用主要是将Retrofit中的call的泛型对象转换成java对象,注意Retrofit中call和okhttp中的call的区别,Retrofit中call封装了okhttp中的call,这也体现了Retrofit底层是okhttp请求。

下面先看看Factory.get()的实现,选择rxjava的实现,看看rxjava是如何获取calladapter的:

@Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //调用Factory的getRawType,就是原始类型
    Class<?> rawType = getRawType(returnType);
    //后面操作,都是当原始类型为rxjava时,做的操作,最终返回callAdapter
    String canonicalName = rawType.getCanonicalName();
    boolean isSingle = "rx.Single".equals(canonicalName);
    boolean isCompletable = "rx.Completable".equals(canonicalName);
    if (rawType != Observable.class && !isSingle && !isCompletable) {
      return null;
    }
    if (!isCompletable && !(returnType instanceof ParameterizedType)) {
      String name = isSingle ? "Single" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }
    if (isCompletable) {
      return CompletableHelper.createCallAdapter(scheduler);
    }
    CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler);
    if (isSingle) {
      return SingleHelper.makeSingle(callAdapter);
    }
    return callAdapter;
  }

流程总结:retrofit的call网络请求  ->  网络数据被converter数据转换器转换成java对象  -> 

callRxJavaCallAdapterFactory extends CallAdapter.Factory   ->  Retrofit将其add到网络适配器的集合中  ->  

Factory.get()获取calladapter  ->  CallAdapter.adapt()将call请求转换成每个平台使用的类型,扩展性在这里。

5)链式调用-build()

new Retrofit.Builder()
                .baseUrl("XXXXX")
                .addCallAdapterFactory(...)
                .build();

进入最后一步的build():

public Retrofit build() {
      //必须的baseUrl 
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //产生Call的工厂,为空则创建默认的请求方式OkHttpClient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      //初始化回调的执行器,用于异步操作后通知主线程更新
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        //空则配置默认的  绑定主线程Executor
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      //将this.adapterFactories网络适配器工厂变量传入集合,用于
      //配置网络请求适配器工厂
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>    
      (this.adapterFactories);
      
      //将平台默认的网络适配器工厂也加入集合
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      //创建配置数据装换器工厂  传入this.converterFactories
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      //作为参数传入
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }

总结:将Retrofit类的成员变量都配置完毕,有值赋值,没值赋值默认值。所以重要的还是开头的7个成员变量。

猜你喜欢

转载自blog.csdn.net/qq_37321098/article/details/88415761