1.背景
Retrofit 是一个基于okHttp为基础的网络请求框架,底层用到了okHttp来进行网络请求,并且结合RXJava能做到非常强大的切换控制作用是现在主流的Android开发框架,并且Retrofit在设计之中用到了大量的设计模式,其实非常适合我们去学习。
2.基础使用
我们可以看到它的基本使用 其实就是用建造者模式建造了一个Retrofit对象 然后创建了一个call对象 ,调用call对象的一个enqueue传入回调接口,在不同的接口中获取不同的回调
Retrofit build = new Retrofit.Builder().baseUrl("wwww.huya.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
IpService ipService = build.create(IpService.class);
Call<IpData> call = ipService.getIpData();
call.enqueue(new Callback<IpData>() {
@Override
public void onResponse(Call<IpData> call, Response<IpData> response) {
}
@Override
public void onFailure(Call<IpData> call, Throwable t) {
}
});
3.源码分析
我们先来看一下Builder这个内部类 具体每个变量已经有解释了,调用了Builder构造函数我们来看一下Platform.get()方法做了什么
private final Platform platform; //平台
private @Nullable okhttp3.Call.Factory callFactory; //call工厂
private HttpUrl baseUrl;//基础url
private final List<Converter.Factory> converterFactories = new ArrayList<>();//转换器工厂
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();//适配器工厂
private @Nullable Executor callbackExecutor; //回调执行器
private boolean validateEagerly;
public Builder() {
this(Platform.get());
}
我们看到其实调用了findPlatform()方法我们跟进去看一下
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
}
其实是根据不同平台调用 我们肯定是Android对象啦 点Android对象
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
其实是做了一些初始化操作
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
然后我们回到基础使用代码的baseUrl其实就是组装了url然后今晚判断是否合法
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
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;
}
我们看到addConverterFactory其实是将转换工厂加入到了集合
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
我们看到addCallAdapterFactory其实也是加入到了集合
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
我们可以看到最终调用build()方法生成一个retrofit对象
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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
这个retrofit里面已经有了 baseUrl 是一个队url的封装对象包含很多东西不需要太纠结 callFactory 这个其实是OkHttpClient 其实是准备调用okHttp的封装好的一个类,converterFactories这个是转换工厂默认是json类型就是我们上面加入的一个那个json转换工厂具体Gson如何转换我们先不用关心callAdapterFactories 这个是数据适配工厂,一般如果我们再上面加入了RXJava的call适配工厂 这个就会被加入进去callbackExecutor 这个是回调的执行 validateEagerly是否提前判断 其实只是我们没有设置也有提供给我们设置的方法
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
最后一个 Retrofit就被我们建造好了
我们接下来看 Retrofit调用的create方法 传入了接口类做了什么
IpService ipService = build.create(IpService.class);
我们可以看到 它先调用了 eagerlyValidateMethods方法然后用了一个代理模式返回了这个对象 我们先看eagerlyValidateMethods这个方法做了啥子
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.adapt(okHttpCall);
}
});
}
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
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;
}
这个方法其实是将接口里面的方法遍历然后每个方法创建自己的ServiceMethod 当然 它也做了缓存操作 如果有就不用创建了 没有的话就创建一个新的ServiceMethod方法 那么ServiceMethod它到底是什么,其实它是一个将接口中的方法进行解析的一个类能 将注解进行解析,持有retrofit对象,将要请求的东西全部搞好放在ServiceMethod这个类中跑包括头 方法 注解 解析器 等
回到create方法 我们可以看到在代理模式中调用了这样的代码
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
拿到了一个ServiceMethod方法 然后创建了一个OkHttpCall,这个OkHttpCall是发起okHttp请求的一个call 然后调用serviceMethod.adapt(okHttpCall); 其实就是把结果构建成上面传入的适配工厂类,我们看一下 如果传入RxJava2CallAdapter的话会做什么操作
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(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;
}
其实就是将结果搞成一个observable 这个是支持RxJava的一个对象我们可以将上面的基本使用改成这样子
Observable<IpData> observable = ipService.getIpData();
这样就可以很好接入RXJava这套框架体系了
我们接下来看enqueue 如果不考虑RXJAVA的话 结果就是调用下面代码
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
其实就是调用serviceMethod的tocall方法组装成一个真正的call请求然后调用OKHTTP的真正请求方法,将真正的网络请求交给OkHttp,返回结果调用parseResponse 方法解析返回的数据,这个就是整个的执行流程
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
4.Retrofit设计模式总结
(1)建造者设计模式
建造者模式在这个框架可以说是随处可见,基本套路就是在Retrofit内部有一个Build 内部类,将要设置的数据全部用过build的方式设置进去,然后返回这个对象,这样就可以一直链式调用,最后通过build方法,将最后的数据new给Retrofit这个对象 这个对象就算是建造完成
(2)外观设计模式
外观设计模式就是让开发者感觉不到其他子系统的存在,比如Retrofit中,有很多子系统 像Call 缓存 等等子系统,但是它不需要让用户知道这些东西,子系统的运行都在Retrofit中可以控制好
(3)代理模式
代理模式就是通过代理的方式去执行方法,分为静态代理和动态代理,动态代码就是像这样 动态执行这个类下面的所有方法
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 {
return serviceMethod.adapt(okHttpCall);
}
});
(4)适配器模式
适配器模式就是可以适配多种数据来源或者数据可能,比如在一开始加入RxJava的适配器,那么我们就可以支持RXJava的操作方式,加入其它平台的就可以适配其它平台的方式
(5)工厂模式
工厂模式就是可以生产多种call根据方法的不同,生产出不同的Call对象
5.总结
通过上面的分析我们要知道的一点就是Retrofit说简单其实是比较简单的,它就是对一个请求进行封装,运用了大量的设计模式,让请求可以更加有扩展性,且可以接入RXJava等,但是它其实是对请求做了处理和封装,真正的请求是交给了OKHttp进行处理,它是做了请求前的前期工作。