2016-05-06 16:07:09
1.先上一张Retrofit的代码结构图:
可以看到,Retrofit自身的结构很简单,代码量也不是很大。红色框部分是一些注解类,就是一些标记。
简单的看一下客户端是如何使用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 }
客户端调用:
1 private void getWeather() { 2 retrofit = new Retrofit.Builder() 3 .baseUrl("http://weatherapi.market.xiaomi.com") 4 .addConverterFactory(GsonConverterFactory.create(gson)) 5 .build(); 6 service = retrofit.create(WeatherDataService.class); 7 Call<MiWeatherData> result = service.getMiWeather("101010100"); 8 9 try { 10 Response<MiWeatherData> r = result.execute(); 11 MiWeatherData data = r.body(); 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 }
2. 几个主要类的UML简图:
2.1 Retrofit和Retrofit.Factory
Retrofit和ServiceMethod使用了Builder模式(省略了Director和Abstract Product的Builder模式)来构建自己,Retrofit的作用很简单,传入需要的参数,构建一个Retrofit对象,然后通过动态代理的方式,得到我们自定义的方法接口的实例,参数中除了baseUrl之外,其他都是可选的,如果没设置会使用默认值。
ServiceMethod就是我们自己调用的方法做一层封装而已,包括解析方法使用的注解、参数等,同时提供方法,生成网络请求需要的Request和解析请求结果。
2.1 CallAdapter和CallAdapter.Factory
CallAdapt的作用是把Call转变成你想要返回的对象,起作用的是adapt方法,CallAdapter.Factory的作用是获取CallAdapter。ExecutorCallAdapterFactory的CallAdapter会将回调方法放到主线程中执行,DefaultCallAdapterFactory不是。两者的CallAdapter能够接受的返回值类型为Call<T>。很明显,RxJavaCallAdapterFactory的CallAdapter能够接受的返回值是Oservable<T>。如果想让的方法直接返回一个对象,可以自定义一个CallAdapter.Factory。代码如下:
1 private class MyCallAdapterFactory extends CallAdapter.Factory { 2 @Override 3 public CallAdapter<?> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) { 4 return new CallAdapter<Object>() { 5 @Override 6 public Type responseType() { 7 return returnType; 8 } 9 10 @Override 11 public <R> Object adapt(Call<R> call) { 12 try { 13 return call.execute().body(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 return null; 17 } 18 } 19 }; 20 } 21 }
Service方法和CallAdapter的对应关系如下:
2.3 Converter和Converter.Factory
Converter的作用是将网络请求结果ResponseBody转换为我们希望的返回值类型。Converter.Factory的作用是获取Converter,这里很明显采用了静态工厂模式。如果你不设置ConverterFactory,那么调用WeatherDataInterface的三个方法都会崩溃,提示:Could not locate ResponseBody converter for class MiWeatherData。这是因为使用了默认的BuiltInConverters,而我们的方法不满足获取到responseBodyConverter的要求,所以崩溃,代码截图如下:
所以,如果不想设置Converter,那么我们的方法返回值必须为ResponseBody或者Void,如果是ResponseBody,且有@Streaming注解,会使用StreamingResponseBodyConverter,否则使用BufferingResponseBodyConveter。这两者基本都是原封不动的返回ResponseBody。而VoidResponseBodyConverter返回null~感觉这点比较坑,干点什么不好,非要返回null
Retrofit提供了多个Converter供选择,比如将Json转换为Object的GsonConverterFactory,如下图:
这也是Retrofit的一大特点---足够的开放、灵活。
2.4 OkHttpCall
OkHttpCall继承自interface Call,主要的作用是调起执行网络请求以及返回当前请求状态状态,但是真正的网络请求其实在okhttp3.Call接口,接口定义如下:
这个接口的实现类是okhttp3.RealCall,可以发现,Retrofit的Call接口和okhttp3的Call接口定义几乎是完全一样的,目的当然是实现OCP,这样做的好处显而易见:
1.利于扩展,retrofit2.Call接口可以有其他的实现类,不一定非要用OkHttp,只不过OkHttpCall用的恰好是OkHttp而已。
2.解耦,为了实现第一个目的,retrofit2.Call接口的存在就是理所当然的。
2.5 ParameterHandler
这是一个辅助类,用于解析我们自己定义的Method,由于我们是通过注解的方式来表达各种信息,比如请求类型(POST、GET)、Query参数、Body等,因此需要解析出来。不在主线,因此不作分析,但是里面的实现蛮复杂的,是个细致活儿。
2.6 RxJavaCallAdapterFactory分析
CallAdapterFactory的作用及工作机理前面已经介绍过了,RxJavaCallAdapterFactory的作用也是一样的,只不过RxJavaCallAdapterFactory中内部又定义了三种CallAdapter:ResponseCallAdapter、ResultCallAdapter和SimpleCallAdapter,根据返回值类型决定到底使用哪个,代码如下:
本质上处理流程是一致的,都是按照RxJava的套路执行请求并处理返回值的。
关于Retrofit中主要类的分解到此结束,之所以这么繁琐的画UML图,目的是为了更加深入的了解作者设计类的思路,比如作者是如何考虑一个类的功能、边界在哪里等。