Retrofit是很多公司常用的网络框架。也是Square公司出品,也属于精品之一。Retrofit的内核是okhttp,Retrofit只负责外层请求的封装,其真正去请求网络的任务依然是okhttp.这样的好处就是简单请求的配置。
基本使用:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.xxxx.com") // 添加请求地址
.addConverterFactory(GsonConverterFactory.create())//使用gson库解析
.build();
IFoodService iFoodService = retrofit.create(IFoodService.class);
Call<ResponseBody> call = iFoodService.getFoodList();
call.enqueue(new Callback<ResponseBody>() {
.........
}
Retrofit.Builder()
Retrofit使用大量的设计模式,比如主对象使用了建造者模式,构造里调用了Platform.get().一个独立的类,一直可以追踪到findPlatform(),通过类加载器的形式,去加载Android平台的Build,这类事系统属性类,包含系统的版本各种信息。如果没有异常,就证明现在是Android平台,创建一个Android类。
public Builder() {
this(Platform.get());
}
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
...
}
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);
}
}
}
Android类继承Platform,而且还有几个重要的方法,defaultCallbackExecutor默认回调的执行器对象,返回一个MainThreadExecutor,而这哥们实现了Exector,而且还用的主线程的Looper,怪不得Retrofit的回调结果是在主线程呢,原因就是它了。
baseUrl
用过retrofit的同学都知道,baseUrl的链接有时候也会踩坑,baseUrl的尾必须得用“/”结尾。究其原因,看代码,checkNotNull检查不为null.
/**
* Set the API base URL.
*
* @see #baseUrl(HttpUrl)
*/
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;
}
build
建造者模式调用build方法,一般就要创建对象了。先创建一个callFactory,其实是OkhttpClient对象,再往下默认的回调执行器对象callbackExecutor,就是从platform里获取的,还记得上面说过嘛。
适配器工厂对象,
转换器工厂对象
然后准备这些对象后,就创建了一个Retrofit对象,把所有的配置就准备好。
/**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> 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;
}
Create 创建接口的实例
create也是一个很重要的方法,它根据接口的方法描述,创建不同请求方法,解析注解,解析参数,然后存入到容器里。这里使用动态代理的形式解析每个方法的各个参数,封装成请求对象,来去网络获取数据。
eagerlyValidateMethods 验证方法,然后去加载方法loadServiceMethod,
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);
}
});
}
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
//serviceMethodCache是一个map集合,它保存方法名和ServiceMethod对象,
//new ServiceMethod.Builder<>(this, method).build();干嘛了呢,
// 大家看看如下代码,这都是请求的配置信息
// ServiceMethod(Builder<R, T> builder) {
// this.callFactory = builder.retrofit.callFactory(); okhttpclient对象
// this.callAdapter = builder.callAdapter; // 适配器对象
// this.baseUrl = builder.retrofit.baseUrl(); 请求链接
// this.responseConverter = builder.responseConverter;响应体的转换器
// this.httpMethod = builder.httpMethod; 请求方法
// this.relativeUrl = builder.relativeUrl; 请求的部分url
// this.headers = builder.headers; 头部信息
// this.contentType = builder.contentType; 请求类型
// this.hasBody = builder.hasBody; 是否有请求体
// this.isFormEncoded = builder.isFormEncoded; 是否是表单类型
// this.isMultipart = builder.isMultipart; 多类型数据
// this.parameterHandlers = builder.parameterHandlers; 参数
// }
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;
}
//parseMethodAnnotation 解析注解
//parseParameter 解析参数
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
。。。。。
return new ServiceMethod<>(this);
}
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
}
。。。。。。
}
parseParameter是解析参数,迭代注解数组,parseParameterAnnotation解析具体的参数,可以看到根据不同的参数类型进行判断,类型很多,拿一个作为列子,query类型最终返回了一个 return new ParameterHandler.Query<>(name, converter, encoded).iterable();这个对象其实还是ParameterHandler的子类,如图,这个对象有好多子类。可以他们有共同点,就是这些都是参数的注解。
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
return result;
}
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
.....
} else if (annotation instanceof Query) {
Query query = (Query) annotation;
String name = query.value();
boolean encoded = query.encoded();
Class<?> rawParameterType = Utils.getRawType(type);
gotQuery = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
} else if (annotation instanceof QueryName) {
} else if (annotation instanceof QueryMap) {
} else if (annotation instanceof Header) {
} else if (annotation instanceof HeaderMap) {
} else if (annotation instanceof Field) {
} else if (annotation instanceof FieldMap) {
} else if (annotation instanceof Body) {
return null; // Not a Retrofit annotation.
}
OKHttpCall 回调逻辑
这个对象干嘛的呢,它是接口实例返回的对象。
Call call = iFoodService.getFoodList();
这个Call其实就是OkHttpCall,是Call的实现类。
在调用Create方法的创建了对象,这也是调用enqueue的逻辑。
大家注意传入callBack对象的逻辑,给大家标记出来。一共4处,在2.3.4处,都是通过call.enquque调用的,这个call在哪赋值的呢, call = rawCall = createRawCall(); 进入方法,可以看到这个对象已经由okHttp接管了,所以这个地方结果回调其实都是由okhttp来做的。
@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) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
//标记1
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
//标记2
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
//标记3
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
//标记4
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
/**
* 这里面callFactory其实就是okHttpClient的对象,还记得retrofit主对象调用build方法,可以回去看看,
* 最终得到的Call,其实就是Okhttp的ReadlCall
**/
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}