zoukankan      html  css  js  c++  java
  • 第二篇:Retrofit调用流程图和使用到的设计模式

    2016-05-08 09:35:58

    这篇文章解析一下Retrofit的调用流程

    1. 先看一下我们是如何使用Retrofit的,代码如下:

     1 public interface WeatherDataService {
     2     @GET("/wtr-v2/temp/realtime")
     3     Call<MiWeatherData> getMiWeather(@Query("cityId") String cityId);
     4 
     5     @GET("/wtr-v2/temp/realtime")
     6     Observable<MiWeatherData> getMiWeatherObservable(@Query("cityId") String cityId);
     7 
     8     @GET("/wtr-v2/temp/realtime")
     9     MiWeatherData getMiWeatherCustomCallAdapter(@Query("cityId") String cityId);
    10 }

    这是获取天气信息的三个请求方法,区别在于返回值不同。下面代码展示了getWeather()是如何调用的,返回值类型时标准的Call<T>:

     1     private void getWeather() {
     2         retrofit = new Retrofit.Builder()
     3                 .baseUrl("http://weatherapi.market.xiaomi.com")
     4                 .addConverterFactory(GsonConverterFactory.create(gson))
     5                 .build();  (1)
     6         service = retrofit.create(WeatherDataService.class);  (2)
     7         Call<MiWeatherData> result = service.getMiWeather("101010100");  (3)
     8 
     9         try {
    10             Response<MiWeatherData> r = result.execute();  (4)
    11             MiWeatherData data = r.body();  (5)
    12             Log.e("David", "ResponseBody data = " + data);
    13             if (data != null) {
    14                 Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.SD);
    15                 Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.cityid);
    16                 Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.WS);
    17             }
    18         } catch (IOException e) {
    19             e.printStackTrace();
    20         }
    21     }

    (1)构建Retrofit对象,因为返回值是json串,所以用GsonConverter,使用默认的CallAdapter,也就是说返回值是Call<T>;

    (2)使用动态代理创建我们自己定义的WeatherDataService接口实例;

    (3)调用接口中真正获取天气信息的方法,返回值是Call<T>;

    (4)调用Call<T>的execute()方法,真正执行网络请求,前面的UML途中提到过,还有一个enqueue()方法,两方法的区别是:execute()是同步且在主线程,enqueue()是异步且在工作线程,这里的工作线程不是我们设置的callbackExecutor,而是有okhttp3来控制的;

    (5)由于getWeather()方法返回的是Response<T>,body()方法取到真正的MiWeatherData对象,Gson已经将json转换为Object;

    2. 调用流程解析

    其实整个调用流程最关键的就是上面提到的5个点,我们顺着这5个点来探究一下Retrofit是怎么调用的。

    第一步就不用多说了,构建Retrofit对象,参数的作用上一篇文章已经做过分析了。

    第二、三步很重要,我们看一下create()方法:

    从(1)可以发现,确实是使用了动态代理,返回值就是我们自定义的接口实例对象T。由于T的所有方法都是抽象方法,当调用T的方法时,会被InvocationHandler拦截,真正的调用会转到InvocationHandler的invoke()方法中,其中method参数就是我们自己的抽象方法。

    (2)处代码基于我们自己的method构造了一个ServiceMethod,构建过程中对方法中的各种注解做了解析,作用前面讲过了。又创建了一个OkHttpCall对象,这个对象将会在被adapt之后返回给客户端,类型取决于客户端的方法返回类型和设置的CallAdapter。这里的代码其实不是很好,耦合性太高,其实本意只是将OkHttpCall转换成客户端需要的返回值,那么CallAdapter对象是否有必要放在ServiceMethod,可以再仔细斟酌一下。

    第四步execute网络请求,看一下源码:

    1处代码创建一个真正的网络请求okhttp3.Call对象,源码如下:

    首先调用了ServiceMethod的toRequest方法得到Request,里面包含了请求类型、请求参数等。然后调用了ServiceMethod的callFactory的newCall方法,这里的CallFactory是Retrofit.Builder的callFactory()设置的参数,默认使用OkHttpClient,我们也可以定义自己的网络请求类,只需要实现okhttp3的Call接口即可。因此默认使用的最终的网络请求类其实是okhttp3.RealCall。

    2处代码执行真正的网络请求,绕了这么一大圈,终于进入正题了,同时对返回值做了解析。

    其中调用了ServiceMethod的toResponse()方法,源码:

    这里真正使用了我们设置的Converter,返回客户端需要类型的返回值。

    3. 最终的流程图

    作者在Retrofit的构建中使用了不少的设计模式,达到了耦合性低、扩展性强、灵活性高的目的。

  • 相关阅读:
    linux常用的命令
    针对无线信道衰落特性分析3G,4G,5G的关键技术异同点
    re-id 资料集
    kissme
    数据集
    matlab print,disp,fprint,fscan
    PCA样本数量少于矩阵维数
    pca降维详细过程
    TOJ 1856 Is It A Tree?
    POJ 2570 Fiber Network
  • 原文地址:https://www.cnblogs.com/wlrhnh/p/5469936.html
Copyright © 2011-2022 走看看