关于Retrofit的使用这里就不再赘述了,还不太了解Retrofit使用的同学
Retrofit简介
今天我们来聊一聊Retrofit的内部实现,通过源码来分析Retrofit的整个执行顺序。
在没有框架的时候,做一次网络请求大概会经过五个步奏:
- 构建request的参数
- 手动开启子线程做http请求
- 在子线程的run方法中具体请求
- 拿到返回的response数据后,回调给上一层
- 在主线程中更新UI
如果没有网络请求框架,然后对多线程又不是太熟悉,就会出现很多问题。比如,请求是否异步,这里就会出现android中常见的错误:Null pointer exception。
所以,在我们还没有造轮子的能力的时候,多去看看优秀框架的源码是有好处的,整个框架的搭建,运用了哪些设计模式,容错处理等等。。
Retrofit 获取实例
- 首先通过构建者模式去获得Retrofit实例
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiContancts.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
- 我们来看看build()方法中具体做了什么
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);
}
不难看出build()方法中主要做了判空处理:
1.baseurl为空,抛出异常;
2.callFactory为空,默认使用OKhttp3的callFactory,这一点也可以看出Retrofit是基于okhttp3做的封装。不会支持URLConnection和OkHttpClient了。
3.callbackExecutor为空,会通过Platform这个类使用defaultCallbackExecutor
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
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);
}
}
}
跟踪源码会发现,最终会通过Handler去做操作。
4.第一个List集合是存储刚刚那个callbackExecutor,第二个List集合是存储将Json转换成实体类的一个工厂或者说是适配器。
5.最后返回一个Retrofit的实例。
Retrofit实例的create()方法
Call<CookListModel> cook = retrofit.create(ApiService.class).getCook(1,20);
通过调用create()方法
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, 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);
}
});
}
其实我看到这里也很懵逼,我们的Http请求方法、参数是通过注解的方式创建的,它是怎么转换成实体对象的?
不急,我们一步一步的看下去
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;
}
这里也用了构建者模式,build()方法中调用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);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
那么,Retrofit到底是怎么把我们定义的接口转换成http请求的呢?
我们来看看ServiceMethod这个类。
Adapts an invocation of an interface method into an HTTP call.
ServiceMethod这个类相当于一个适配器,将interface转换成http的请求,再通过OkHttp去做网络请求。
所以说,真正的关键代码是:
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
Retrofit内部大致的执行流程就是这样,如果想要更深入的去研究Retrofit的话,建议大家利用debug一步一步的跟踪源码分析,这样的话会更加容易理解一点。