一、定义
Retrofit是一个网络请求封装框架,默认使用OkHttp进行网络请求,只是简化了用户的网络请求参数的封装。
二、使用
1.创建Retrofit实例
2.定义网络请求接口,并为接口中的方法添加相应的注解
3.通过动态代理生成网络请求对象
4.通过网络请求适配器将网络请求对象进行平台适配
5.通过网络清执行器,发送网络请求
6.通过数据解析器解析数据
7.通过回调执行器,切换线程
8.用户在主线程处理返回数据
网络接口
public interface WanAndroidService {
@GET("wxarticle/chapters/json")
Call<WxArticleBean> wxarticle();
}
使用
// 1.通过构造器模式,创建Retrofit对象
retrofit = new Retrofit.Builder()
.baseUrl("https://wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
//2.通过create的动态代理实现接口对象
WanAndroidService service = retrofit.create(WanAndroidService.class);
//3.调用接口方法,返回Call对象
Call<WxArticleBean> listCall = service.wxarticle();
//4.通过Call对象,异步请求网络,并使用Callback接收返回数据
listCall.enqueue(new Callback<WxArticleBean>() {
@Override
public void onResponse(Call<WxArticleBean> call, Response<WxArticleBean> response) {
Log.e(TAG,"thread:"+Thread.currentThread());
}
@Override
public void onFailure(Call<WxArticleBean> call, Throwable t) {
Log.e(TAG,"Throwable:"+t.getMessage());
}
});
上面就是一次网络请求的简单过程,使用起来确实很方便吧。只需要在接口中通过注解将需要的请求参数输入,而不需要关心怎么拼接请求参数,也不需要关心怎么处理返回数据及线程的切换。
三、原理
在看原理之前,我们需要带着几个问题来看①retrofit为什么不需要接口实现类的②它怎样将参数拼接起来的③返回的参数是怎么解析的④线程的切换是怎么做的。这样看源码时才不会陷入到源码中不可自拔。
1.通过构造器模式,创建Retrofit对象
先看Retrofit的Builder做了什么
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) {//判断是否有android sdk
return new Android();//返回android平台
}
} catch (ClassNotFoundException ignored) {
}
......
return new Platform();
}
判断是否有android sdk,有就创建Android
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 {
//getMainLooper获得的Looper是主线程的,所以创建的handler是主线程的
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
只是重写了父类的defaultCallbackExecutor()和defaultCallAdapterFactory(),但是看到比较熟悉的代码Handler handler = new Handler(Looper.getMainLooper()),这是比较典型的切换到主线程的方式。这里先猜测是使用handle切换线程
回到Retrofit构造器模式中,this(Platform.get())跳到的位置其实没啥
Builder(Platform platform) {
this.platform = platform;
// 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());
}
链式调用只是将需要的配置放入,最终创建Retrofit看build()方法
public Retrofit build() {
if (baseUrl == null) {//如果baseUrl为空,直接报错
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {//如果没有设置callFactory
callFactory = new OkHttpClient();//创建一个OkHttpClient
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {//如果没有设置callbackExecutor
//还记得之前获得的Android吗?这里返回的MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//将Android的ExecutorCallAdapterFactory添加到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);
}
build方法就是把之前设置过的值,以及没有设置,但是必须的值给赋值好,传入Retrofit构造方法来创建Retrofit对象。这里要记得callbackExecutor 是MainThreadExecutor,CallAdapter.Factory是ExecutorCallAdapterFactory,它们都是通过platform对象获得的。
2.将接口转为对象
public <T> T create(final Class<T> service) {
//判断传入的类是否是接口以及接口中的方法是否大于0
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)) {//默认是false
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//将接口方法中的参数报错在ServiceMethod中
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
3.调用接口中的方法,返回Call对象
在调用接口的方法时,其实走的是动态代理的invoke()方法,①先将接口方法中的参数及注解解析之后存放在ServiceMethod对象中,②创建一个OkHttpCall对象,③通过CallAdapter的adapter方法将OkHttpCall转接成一个Call对象。
①先将接口方法中的参数及注解解析之后存放在ServiceMethod对象中
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
//缓存中是否有了,有的话,直接返回
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {//如果缓存中没有,通过构造器模式创建一个新的ServiceMethod
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
看看ServiceMethod的构造器模式
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
callAdapter = createCallAdapter();//获得callAdapter对象
responseType = callAdapter.responseType();
......
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];
......
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
......
//解析方法里的入参
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
......
//创建ServiceMethod对象
return new ServiceMethod<>(this);
}
build()中主要做的是:获得callAdapter对象、获得数据解析器、解析方法上的注解、解析方法里的入参这几个操作
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
......
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
通过retrofit拿到CallAdapter,这个方法是在Retrofit中
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
......
}
skipPast是null,还记得Retrofit构造时,只添加了ExecutorCallAdapterFactory进去了,所以indexOf返回的是-1,start是0,遍历数组,找到returnType, annotations相匹配的对象,所以最终拿到的还是ExecutorCallAdapterFactory。
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
createResponseConverter方法同样是通过方式,从Retrofit的converterFactories中的相匹配的数据解析器。
parseMethodAnnotation方法是将方法上的注解解析,判断注解的类型,然后封装请求方式,
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是使用入参和入参的注解来生成对应的入参对象
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
......
result = annotationAction;
}
......
return result;
}
返回ParameterHandler对象,可以看到它的子类有Header、Path、Query等对应的注解类名。最终将这些信息放入到ServiceMethod对象中。
②创建一个OkHttpCall对象
创建OkHttpCall对象没有什么,就是将ServiceMethod和入参传入
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
③通过CallAdapter的adapter方法将OkHttpCall转接成一个Call对象。
serviceMethod.callAdapter.adapt(okHttpCall)
从ServiceMethod中获得CallAdapter,我们保存的CallAdapter是ExecutorCallAdapterFactory,所以这里调用adapter方法是ExecutorCallAdapterFactory中的CallAdapter的adapter方法
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
} else {
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
public Type responseType() {
return responseType;
}
//serviceMethod.callAdapter.adapt最终调的是这个方法
public Call<Object> adapt(Call<Object> call) {
//callbackExecutor是MainThreadExecutor
//call是OkHttpCall
return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
}
};
}
}
里面是创建了一个静态内部类ExecutorCallbackCall,将callbackExecutor和OkHttpCall传入进去。
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
......
}
这里其实是一个委派模式,OkHttpCall最终回调操作是交给这个类来完成的。
4.通过Call对象,异步请求网络,并使用Callback接收返回数据
拿到OkHttpCall对象之后,就是执行enqueue方法了。
public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
......
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
......
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 {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
......
});
}
因为底层使用了OkHttp做网络请求,所以在调用enqueue,需要创建OkHttp的Call对象.
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;
}
这里就是从ServiceMethod中获取到接口的方法参数封装成OkHttp的Request,同时创建一个okhttp的call对象,通过call的enqueue方法进行实际的网络请求。
还记得之前的委派模式,在OkHttpCall做enqueue时,也会调用到ExecutorCallbackCall的enqueue方法
public void enqueue(final Callback<T> callback) {
Utils.checkNotNull(callback, "callback == null");
this.delegate.enqueue(new Callback<T>() {
public void onResponse(Call<T> call, final Response<T> response) {
ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
public void run() {
if (ExecutorCallbackCall.this.delegate.isCanceled()) {
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
public void onFailure(Call<T> call, final Throwable t) {
ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
在回调onResponse和onFailure时,会通过CallbackExecutor的execute方法,将线程切换到主线程中,这样就不需要开发者自己去切换线程了。
解析返回数据是在parseResponse方法中
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {//这里是代表成功但返回数据为空时,直接返回
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
......
}
}
这一步是将OkHttp的Response的数据取出,重新封装到自己的Response中去。通过ServiceMethod的toResponse将body的数据转换为所需要的bean对象
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
这个responseConverter就是通过GsonConverterFactory生成的,具体是在ServiceMethod构造模式中。
至此,retrofit的原理就解析完了,上面的几个问题应该也有了答案。