第三方开源库 Retrofit - 源码设计模式分析
2017-12-21 16:15
676 查看
Retrofit 这个开源库对我成长还是挺大的,自己虽不常用,但他的源码封装思想,却需要用到实际的开发中。这些年有两本书一直都在看 《Android的源码》和《 JakeWharton的源码》。JakeWharton 映象最深的是自己刚做Android时的 ViewPageIndicator, 那个时候这个库才刚开源,如今又是几个年头过去了,想想一个 Android 的十几年的大神叫我怎能不激动,所以他所有的源码我都不曾放过。
设计模式有很多的理论基础,借此机会我们就看看到底都应该怎么用,也可以巩固之前的一些知识,所以 Retrofit 的源码分析,我们主要来分析他的设计模式,他的封装思想。总结里面的源码经验,方可优化自己的网络引擎。
create()这个方法,个人认为 Retrofit 能做到解耦就是因为动态代理的设计模式用得好,这种模式我们也是经常用到,有很多的体现形式,比如之前所讲的 Android插件化架构 - 拦截Activity的启动流程绕过AndroidManifest检测 主要是用来 Hook 拦截方法,而 Retrofit 这里主要是用来解耦,后面 MVP 部分我们则主要用做AOP切面编程,等等。
工厂设计模式又分为:简单工厂,抽象工厂,工厂方法。addConverterFactory(GsonConverterFactory.create()) 好处就不用说了吧?当然这个地方还影藏着另一种设计模式,如有不了解你可以点击标题进入相应的链接。
突然发现没写过 Adapter 设计模式的文章只录制了视频,有时间我会补一下的。我们都知道 Retrofit 是支持 RxJava 的,也就是说 OkHttp + RxJava + Retrofit 这本该是一套。我们看下是怎么办到的:
这里用自己的话总结就是 RxJavaCallAdapter 实现了 CallAdapter 目标接口,调用 adapt 方法把 Call 转换适配成了 Observable。再通俗一点就是我想要的是 RxJava 的 Observable 对象,但是我只有 Call 这个怎么办?所以采用适配器模式。
不到 20 个类,23 种设计模式 Retrofit 运用占了一大半,像 观察者设计模式、策略设计模式,享元设计模式、门面设计模式、单例设计模式、原型设计模式 、装饰设计模式 等等都在其源码中有体现。
抛出一个问题,Retrofit.Builder 中有一个 baseUrl 用作主路径地址,但是开发中可能会出现多个 baseUrl 这种情况,不知看了源码后有没有更好的解决方案。
所有分享大纲:Android进阶之旅 - 系统架构篇
视频讲解地址:https://pan.baidu.com/s/1dE7mUjR
设计模式有很多的理论基础,借此机会我们就看看到底都应该怎么用,也可以巩固之前的一些知识,所以 Retrofit 的源码分析,我们主要来分析他的设计模式,他的封装思想。总结里面的源码经验,方可优化自己的网络引擎。
1.Builder 设计模式
static { OkHttpClient httpClient = new OkHttpClient.Builder() // 添加日志打印 .addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { Log.d("TAG", message); } }).setLevel(HttpLoggingInterceptor.Level.BODY)) .build(); Retrofit retrofit = new Retrofit.Builder() // 主路径 .baseUrl("http://ppw.zmzxd.cn/index.php/api/v1/") // 添加转换工厂 .addConverterFactory(GsonConverterFactory.create()) // 配置 OkHttpClient .client(httpClient).build(); // 创建 ServiceApi mServiceApi = retrofit.create(ServiceApi.class); }
2.动态代理设计模式
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); } }); }
create()这个方法,个人认为 Retrofit 能做到解耦就是因为动态代理的设计模式用得好,这种模式我们也是经常用到,有很多的体现形式,比如之前所讲的 Android插件化架构 - 拦截Activity的启动流程绕过AndroidManifest检测 主要是用来 Hook 拦截方法,而 Retrofit 这里主要是用来解耦,后面 MVP 部分我们则主要用做AOP切面编程,等等。
3.工厂设计模式
abstract class Factory { /** * Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if * {@code type} cannot be handled by this factory. This is used to create converters for * response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>} * declaration. */ public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } /** * Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if * {@code type} cannot be handled by this factory. This is used to create converters for types * specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap} * values. */ public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; } /** * Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if * {@code type} cannot be handled by this factory. This is used to create converters for types * specified by {@link Field @Field}, {@link FieldMap @FieldMap} values, * {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path}, * {@link Query @Query}, and {@link QueryMap @QueryMap} values. */ public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } }
工厂设计模式又分为:简单工厂,抽象工厂,工厂方法。addConverterFactory(GsonConverterFactory.create()) 好处就不用说了吧?当然这个地方还影藏着另一种设计模式,如有不了解你可以点击标题进入相应的链接。
4.Adapter 适配器模式
public interface CallAdapter<T> { // 返回请求后,转换的参数Type类型 Type responseType(); // 接口适配 <R> T adapt(Call<R> call); }
突然发现没写过 Adapter 设计模式的文章只录制了视频,有时间我会补一下的。我们都知道 Retrofit 是支持 RxJava 的,也就是说 OkHttp + RxJava + Retrofit 这本该是一套。我们看下是怎么办到的:
final class RxJavaCallAdapter<R> implements CallAdapter<R, Object> { RxJavaCallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync, boolean isResult, boolean isBody, boolean isSingle, boolean isCompletable) { } @Override public Type responseType() { return responseType; } @Override public Object adapt(Call<R> call) { OnSubscribe<Response<R>> callFunc = isAsync ? new CallEnqueueOnSubscribe<>(call) : new CallExecuteOnSubscribe<>(call); // 省略代码 OnSubscribe<?> func; if (isResult) { func = new ResultOnSubscribe<>(callFunc); } else if (isBody) { func = new BodyOnSubscribe<>(callFunc); } else { func = callFunc; } Observable<?> observable = Observable.create(func); if (scheduler != null) { observable = observable.subscribeOn(scheduler); } return observable; } }
这里用自己的话总结就是 RxJavaCallAdapter 实现了 CallAdapter 目标接口,调用 adapt 方法把 Call 转换适配成了 Observable。再通俗一点就是我想要的是 RxJava 的 Observable 对象,但是我只有 Call 这个怎么办?所以采用适配器模式。
5.模板设计模式
abstract class ParameterHandler<T> { abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException; static final class Query<T> extends ParameterHandler<T> { private final String name; private final Converter<T, String> valueConverter; private final boolean encoded; Query(String name, Converter<T, String> valueConverter, boolean encoded) { this.name = checkNotNull(name, "name == null"); this.valueConverter = valueConverter; this.encoded = encoded; } @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException { if (value == null) return; // Skip null values. String queryValue = valueConverter.convert(value); if (queryValue == null) return; // Skip converted but null values builder.addQueryParam(name, queryValue, encoded); } } }
不到 20 个类,23 种设计模式 Retrofit 运用占了一大半,像 观察者设计模式、策略设计模式,享元设计模式、门面设计模式、单例设计模式、原型设计模式 、装饰设计模式 等等都在其源码中有体现。
抛出一个问题,Retrofit.Builder 中有一个 baseUrl 用作主路径地址,但是开发中可能会出现多个 baseUrl 这种情况,不知看了源码后有没有更好的解决方案。
所有分享大纲:Android进阶之旅 - 系统架构篇
视频讲解地址:https://pan.baidu.com/s/1dE7mUjR
相关文章推荐
- 透过Retrofit使用看其源码设计模式
- Android源码设计模式分析开源项目
- [置顶] 透过Retrofit使用看其源码设计模式
- Android源码设计模式分析一期发布
- Android源码设计模式分析开源项目
- Retrofit源码设计模式解析(上)
- Android 最常用的设计模式十 安卓源码分析——策略模式(Strategy)
- Mybatis3源码分析(08)-加载Configuration-使用到的设计模式
- (六)Tomcat源码解析 - Tomcat 系统架构与设计模式(二)-设计模式分析
- Builder设计模式和AlertDialog的源码分析
- Retrofit 分析 - 经典设计模式案例
- Hessian源码分析之设计模式篇(八)
- 第三方开源库 RxJava - 基本使用和源码分析
- Retrofit源码设计模式解析(上)
- Retrofit源码解读(六)--Retrofit中的设计模式
- 设计模式--代理模式(附源码分析)
- Dubbo系列(八)Dubbo源码分析之Dubbo中采用的设计模式
- Dagger2, Retrofit和MVP设计模式案例分析
- Java设计模式-代理模式之动态代理(附源码分析)
- 从源码的角度带你分析Glide整体加载流程以及设计模式