Retrofit2原理简介

Retrofit现在大家基本都用过,它不做网络请求,只负责生成网络请求的对象,网络请求交由OkHttp去完成。
一、Retrofit2的基本使用
1、引用

    implementation'com.squareup.retrofit2:retrofit:2.3.0'
    implementation'com.squareup.retrofit2:retrofit-converters:2.3.0'
    implementation'com.squareup.retrofit2:retrofit-adapters:2.3.0'

如需要搭配gson,rxjava等同时使用,就继续添加相关引用

implementation'com'com.squareup.retrofit2:converter-gson:2.3.0'
implementation'com'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

2、定义接口

public interface NewsApi { 

/**
     * 获取首页的新闻列表
     *
     * @param map
     */
    @FormUrlEncoded
    @POST("api.php?s=/News/getNewsListCache")
    Call getNewsList(@FieldMap() Map map);

上边的接口函数getNewsList中定义了请求方式(POST)、URL(“api.php?s=/News/getNewsListCache”)、返回值类型( Observable>)、请求参数(map)。
3、生成retrofit对象

 retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(FastJsonConverter.create())
                    .build();

生成retrofit对象时,我们可以在过程中添加json转换器等
4、生成网络请求对象

NewsApi  newsApiService = retrofit.create(NewsApi.class)//生成接口实例对象
Call callWorker = newsApiService.getNewsList(map)//生成网络请求对象

首先通过create方法生成接口实例对象,然后生成网络请求对象。
5、执行网络请求

callWorker.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {...}
            @Override
            public void onFailure(Call call, Throwable t) {...}
        });

二、生成网络请求对象原理
retrofit的作用就是生成网络请求对象,那么我们来重点看一下,它是如何生成这个对象的

NewsApi  newsApiService = retrofit.create(NewsApi.class)//生成接口实例对象

生成接口实例对象时,调用了retrofit的create方法,我们点进去看一下源码

public  T create(final Class service) {
    Utils.validateServiceInterface(service);//判断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 serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
 
  

在上边的方法中,最终要的就是动态代理中,通过InvocationHandler处理的以下三行代码

         (1)   ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
         (2) OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
         (3)return serviceMethod.callAdapter.adapt(okHttpCall);
 
  

代码(1)中生成了一个ServiceMethod类型对象,这个ServiceMethod是什么呢?ServiceMethod类包含了我们进行网络请求的所有基本信息,那么这个loadServiceMethod方法做了什么操作返回的ServiceMethod对象呢?

 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;
  }

代码很简单,其中serviceMethodCache是一个ConcurrentHashMap,用于存储ServiceMethod,通过查找serviceMethodCache中是否已经存储了相关ServiceMethod对象,如果有则返回,没有就生成新的,并将其存入serviceMethodCache中。
好了,现在我们知道(1)代码中得到了一个包含网络请求信息的对象,看看(2)中做了什么

(2) OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 
  

第二句代码生成了一个OkHttpCall对象,那这个OkHttpCall对象就是OkHttpClient框架中的网络请求执行对象吗?当然不是,为了尽可能的与OkHttpClient解耦,retrofit此处所生成的OkHttpCall,是其内部自定义的实现了retrofit2.Call接口的OkHttpCall,然后在(3)中通过adapter转换器,将这个OkHttpCall转换成我们需要的返回值类型。

 (3)return serviceMethod.callAdapter.adapt(okHttpCall);

通过ServiceMethod中的callAdapter对象的adapt方法,对上边生成的okHttpCall进行转换,我们来看一下这个callAdapter,进入ServiceMethod类,找到这个callAdapter

CallAdapter callAdapter;

  public ServiceMethod build() {
      callAdapter = createCallAdapter();
      ...
      ...
  }

  private CallAdapter createCallAdapter() {
  ...
  ...
        return (CallAdapter) retrofit.callAdapter(returnType, annotations);
    }

又回到了retrofit中

  public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

 public CallAdapter nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
	...
	...
  }

现在我们看到了,callAdapter就是在这个方法中通过遍历adapterFactories返回的,那adapterFactories又是个什么鬼呢?

 final List adapterFactories;
 
 Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List converterFactories, List adapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

原来它是在Retrofit构造方法中传递进来的一个内部为CallAdapter.Factory类型的list,这回清楚了,原来当初构建的时候传递进来的adapter构造器是什么,就会根据该构造器的内部逻辑,对返回值类型进行转换,不过话又说回来了,我们在没有调用addCallAdapterFactory进行传递的时候貌似也可以正常进行啊,我们来看一下Retrofit的build方法

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 adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List converterFactories = new ArrayList<>(this.converterFactories);

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

在这里,我们看到了这样两行代码

  List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

原来Retrofit在创建的时候自动为我们添加了一个默认的AdapterFactory,同时,我们还注意到

   okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

就是说如果我们在构建retrofit对象的时候,如果没有主动调用client方法去添加OkHttpClient,那么Retrofit会贴心的为我们创建一个默认的OkHttpClient,当然,如果你想要自己对OkHttpClient进行一些自定义设置,就需要手动来添加了。

接下来问题又来了,CallAdapter中的adapter到底是怎么进行类型转换的呢,在这里,我们首先来看一下Retrofit给我们添加的默认的CallAdapter如何进行转换的

进入Platform类中的defaultCallAdapterFactory方法

  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

进入DefaultCallAdapterFactory类中,代码只有几行

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }

    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call adapt(Call call) {
        return call;
      }
    };
  }
}
 
  

在上边的get中我们看到,返回的CallAdapter的adapt方法中,直接将传递进来的Call对象返回,并没有做任何处理,好吧,白给的确实不能要求人家做太多东西。

那如果我们自己手动添加CallAdapterFactory呢?先来看一下与不添加时候的使用区别。
在开始的时候,我们知道,在生成了网络请求对象callWorker之后,我们主动通过调用enqueue方法,执行了网络请求(此处不再详细说明请求过程,感兴趣的同学可自行查看源码);那么如果我们在创建retrofit对象时添加了RxJava2CallAdapterFactory呢?

retrofit.create(NewsApi.class)
                .getNewsBanner(map)
                .map(new HttpFunction<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseObserver() {
                    @Override
                    public void onSubscribe(Disposable d) {
                     
                    }

                    @Override
                    public void onNext(NewsBean value) {
             
                    }

                    @Override
                    public void onError(Throwable t) {
                   
                    }
                });

为什么这时候不需要再调用enqueue或者execute方法来执行网络请求,而是只要等结果就可以了呢?
这个RxJava2CallAdapterFactory一定有什么猫腻,我们来看一下这个类到底做了什么。

@Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
...
    return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

进入RxJava2CallAdapter类

@Override public  Object adapt(Call call) {
    Observable> responseObservable = new CallObservable<>(call);

    Observable observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

这里,我们看到,call被转换成了我们在配合RxJava2CallAdapterFactory使用的时候得到的Observable类型,那么这个转换过程是什么样的呢?

进入CallObservable类

final class CallObservable extends Observable> {
  private final Call originalCall;

  CallObservable(Call originalCall) {
    this.originalCall = originalCall;
  }

  @Override protected void subscribeActual(Observer> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call call = originalCall.clone();
    observer.onSubscribe(new CallDisposable(call));

    boolean terminated = false;
    try {
      Response response = call.execute();
      if (!call.isCanceled()) {
        observer.onNext(response);
      }
      if (!call.isCanceled()) {
        terminated = true;
        observer.onComplete();
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (terminated) {
        RxJavaPlugins.onError(t);
      } else if (!call.isCanceled()) {
        try {
          observer.onError(t);
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }
  }

在这里我们看到了这么一句代码

  Response response = call.execute();

原来RxJava2CallAdapterFactory所生成的CallAdapter,不仅仅帮助我们将返回类型由Call转换成了Observable,还在过程中执行了 call.execute()也就是网络请求动作,怪不得我们使用RxJava2CallAdapterFactory的时候不需要自己手动执行网络请求。

好了,到这里Retrofit2的功能原理我们大概就了解了,主要就是生成了一个网络请求对像,然后我们通过操作这个对象来执行网络请求,并得到我们所期望的返回值类型。

你可能感兴趣的:(Retrofit2原理简介)