public static <T> T createApi(Class<T> clazz, String url) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(clazz);
}
Builder(Platform platform) {
converterFactories.add(new BuiltInConverters()); //保存默认的内置转换工厂
}
public Builder baseUrl(String baseUrl) {
HttpUrl httpUrl = HttpUrl.parse(baseUrl); //根据baseUrl创建HttpUrl
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
this.baseUrl = baseUrl; //赋值baseUrl
return this;
}
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 {
ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //(1)获取或创建 ServiceMethod
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //(2)创建OkHttpCall实例
return serviceMethod.callAdapter.adapt(okHttpCall); //(3)调用设置的Adapter.adapt()转换OkHttpCall实例
}
});
Retrofit使用动态代理的形式拦截设置接口中的所有抽象方法,关于动态代理的内容点击查看,在动态代理的invoke()方法中主要完成以下过程:
上面的三个过程就是Retrofit的主要工作原理,下面一一分析
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method); //(1)从缓存的Map中获取ServiceMethod
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build(); //(2)创建实例、解析方法和参数的注解
serviceMethodCache.put(method, result); (3)缓存ServiceMethod
}
}
return result;
}
loadServiceMethod()首先从缓存中获取,如果缓存中没有则创建实例,这里设置缓存是为了当多次请求同一个接口时,避免每次都要反射获取注解,首次解析后缓存之后调用此方法时直接使用;
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit; //Retrofit实例
this.method = method; //Method方法
this.methodAnnotations = method.getAnnotations(); //获取方法的注解类型
this.parameterTypes = method.getGenericParameterTypes(); //获取方法的参数类型集合
this.parameterAnnotationsArray = method.getParameterAnnotations(); //获取参数注解集合
}
public ServiceMethod build() {
callAdapter = createCallAdapter(); // (1)
responseType = callAdapter.responseType(); //获取Adapter的返回类型
responseConverter = createResponseConverter(); //(2)
for (Annotation annotation : methodAnnotations) { //(3)
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); //(4)
}
return new ServiceMethod<>(this); //(5)
}
build()方法中执行的逻辑很多,完成了所有的转换和注解的处理,总结以下:
//遍历方法注解,确定请求方式、请求地址、请求参数
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); //根据选择的方式,转换方法和参数value,并解析请求参数
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); //GET请求
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); //POST请求
}
首先根据注解解析请求方式,并获取设置的方法注解参数最终拼接请求地址,以GET方式请求为例分析,保存了请求方法GET、请求体、请求Url
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
this.httpMethod = httpMethod; //保存方法“GET”
this.hasBody = hasBody; //是否有请求体,针对POST请求
this.relativeUrl = value; //赋值实际请求的Url(也就是注解中的路径)
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount]; //创建ParameterHandler实例,保存参数下标、参数类型、参数注解的解析结果
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p]; //(1)
Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; //(2)获取当前参数注解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); //(3)解析参数类型和参数注解创建ParameterHandler实例,并保存在数组中
}
从上面代码看出,parameterAnnotationsArray会遍历获取所有的获取当前注解的参数类型,解析每个参数类型和参数注解创建ParameterHandler实例,并保存在数组中
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;
}
private ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation) {
//处理Url注解
if (annotation instanceof Url) {
if (gotUrl) { //Url只能出现一次,如果已经出现过了抛出异常
throw parameterError(p, "Multiple @Url method annotations found.");
}
if (gotPath) { //@Path和@Url不能同时在参数注解中使用
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
if (gotQuery) { //@Url不能出现在@Query之后
throw parameterError(p, "A @Url parameter must not come after a @Query");
}
if (relativeUrl != null) { //如果在方法注解中设置了Url,参数中不能使用@Url注解
throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod);
}
gotUrl = true; //此处赋值goUrl位true
return new ParameterHandler.RelativeUrl(); //创建ParameterHandler实例,此处为实现类RelativeUrl
}
//处理Path注解
if (annotation instanceof Path) {
if (gotQuery) { //@Path 不能出现在@Query之后
throw parameterError(p, "A @Path parameter must not come after a @Query.");
}
if (gotUrl) {//@Path 和@Url不能一起使用
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
if (relativeUrl == null) {//使用@Path必须在方法注解中设置请求Url
throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
}
gotPath = true; //
Path path = (Path) annotation;
String name = path.value(); //获取@Path注解名称,请求数据的Key
validatePathName(p, name); //校验参数合法性
Converter<?, String> converter = retrofit.stringConverter(type, annotations); //获取设置的String转换
return new ParameterHandler.Path<>(name, converter, path.encoded()); //创建Path实例
}
//处理Query注解
if (annotation instanceof Query) {
Query query = (Query) annotation;
String name = query.value(); //获取@Query注解名称
boolean encoded = query.encoded();
gotQuery = true; //
return new ParameterHandler.Query<>(name, converter, encoded);
}
}
//处理Head注解
if (annotation instanceof Header) {
Header header = (Header) annotation;
String name = header.value(); //获取@head注解名称
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Header<>(name, converter); //
}
// 处理Field参数注解
if (annotation instanceof Field) {
if (!isFormEncoded) { //使用@Field注解必须在方法注解上声明@FormUrlEncoded注解
throw parameterError(p, "@Field parameters can only be used with form encoding.");
}
Field field = (Field) annotation;
String name = field.value(); //获取@Field注解名称
boolean encoded = field.encoded();
gotField = true; //
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Field<>(name, converter, encoded);
}
//处理FieldMap参数注解
if (annotation instanceof FieldMap) {
if (!isFormEncoded) { // //使用@Field注解必须在方法注解上声明@FormUrlEncoded注解
throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
}
…….
Converter<?, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
gotField = true;
return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded()); //创建ParameterHandler.FieldMap<>实例
}
//处理@part注解
else if (annotation instanceof Part) {
if (!isMultipart) { //对于@part注解必须在方法上添加@Multipart注解
throw parameterError(p, "@Part parameters can only be used with multipart encoding.");
}
Part part = (Part) annotation;
gotPart = true;
String partName = part.value(); //获取@Part注解名称
Class<?> rawParameterType = Utils.getRawType(type);
if (partName.isEmpty()) { //注解名称为空的情况
} else { //当@part注解名称不为空
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding()); // 设置上传文件参数的头部信息
return new ParameterHandler.Part<>(headers, converter); // 创建ParameterHandler.Part实例
}
//处理@partMap注解
if (annotation instanceof PartMap) {
if (!isMultipart) { // 添加@Multipart注解
throw parameterError(p, "@PartMap parameters can only be used with multipart encoding.");
}
gotPart = true;
Class<?> rawParameterType = Utils.getRawType(type);
…...
Converter<?, RequestBody> valueConverter =
retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);
PartMap partMap = (PartMap) annotation;
return new ParameterHandler.PartMap<>(valueConverter, partMap.encoding());
//创建 ParameterHandler.PartMap<>实例
}
// 处理@Body注解
if (annotation instanceof Body) {
if (isFormEncoded || isMultipart) { //@Multipart和@FormEncoded必须有一个
}
if (gotBody) { //已经设置了@Body
throw parameterError(p, "Multiple @Body method annotations found.");
}
gotBody = true;
return new ParameterHandler.Body<>(converter); //创建 ParameterHandler.Body<>实例
}
}
上面的代码虽然很多但逻辑很清晰,就是针对注解类型Url、Path、Query、QueryName、QueryMap、Header、HeaderMap、Field、FieldMap、Part、PartMap、Body分别处理参数,除了必要的判断外,根据不同注解创建ParameterHandler对应的子类,保存注解值和对应的类型转换器,具体的见注释
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
serviceMethod.callAdapter.adapt(okHttpCall)
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
Response<T> response = call.execute();
}
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
executed = true;
call = rawCall; //赋值rawCall,此时拿到的初始化时创建Okhttp的Call实例
if (call == null) {
try {
call = rawCall = createRawCall(); //(1)
}
}
}
if (canceled) { //取消请求
call.cancel();
}
return parseResponse(call.execute()); //
}
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args); //
okhttp3.Call call = serviceMethod.callFactory.newCall(request); //
return call;
}
除去外层的Adapter封装,请求最终调用OkHttpCall.execute()方法,execute()中的逻辑很清除,首先根据注解解析后的数据创建Okhttp中的Request对象那个,然后调用初始化时设置OkhttpClient创建Call实例
Request toRequest(Object... args) throws IOException {
//(1)封装保存所有请求信息,RequestBuilder内部创建了OKhttp中的Request.Builder requestBuilder;
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,contentType, hasBody, isFormEncoded, isMultipart);
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers; //保存所有参数注解和参数注解信息的数组
int argumentCount = args != null ? args.length : 0;
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]); // (2)为每个参数和注解执行apply()方式(前面针对注解创建的ParameterHandler),将注解的参数注解和参数值进行拼接处理
}
return requestBuilder.build(); //(3)创建Okhttp的Request实例
}
//以Url注解为例
static final class RelativeUrl extends ParameterHandler<Object> {
@Override void apply(RequestBuilder builder, Object value) {
builder.setRelativeUrl(value); // 直接设置RequestBuilder请求的Url
}
}
@Override void apply(RequestBuilder builder, T value) throws IOException {
builder.addPathParam(name, valueConverter.convert(value), encoded); //首先对参数值进行转换,然后在url中设置请求参数
}
void addPathParam(String name, String value, boolean encoded) {
relativeUrl = relativeUrl.replace("{" + name + "}", canonicalizeForPath(value, encoded)); // 针对Path注解替换Url中的占位符字符串
}
@Override void apply(RequestBuilder builder, T value) throws IOException {
builder.addQueryParam(name, valueConverter.convert(value), encoded); // 对参数进行转换
}
void addQueryParam(String name, String value, boolean encoded) {
if (relativeUrl != null) {
urlBuilder = baseUrl.newBuilder(relativeUrl); //创建Okhttp中HttpUrl。Builder
relativeUrl = null;
}
if (encoded) {
urlBuilder.addEncodedQueryParameter(name, value); //加密设置,
} else {
urlBuilder.addQueryParameter(name, value); //直接添加参数和Value,最终都会将数据保存在encodedQueryNamesAndValues集合中
}
}
@Override void apply(RequestBuilder builder, T value) throws IOException {
builder.addHeader(name, valueConverter.convert(value));
}
void addHeader(String name, String value) {
if ("Content-Type".equalsIgnoreCase(name)) { //如果设置Content-Type暂时保存在contentType中,在创建Request中时设置
MediaType type = MediaType.parse(value);
contentType = type; //保存ContentType
} else {
requestBuilder.addHeader(name, value); //直接调用Okhttp中的Request。Builder设置头部信息
}
}
@Override void apply(RequestBuilder builder, T value) throws IOException {
builder.addFormField(name, valueConverter.convert(value), encoded);
}
void addFormField(String name, String value, boolean encoded) {
if (encoded) {
formBuilder.addEncoded(name, value); //调用FormBody.Builder添加参数值
} else {
formBuilder.add(name, value);
}
}
@Override void apply(RequestBuilder builder, Map<String, T> value) throws IOException {
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey(); //获取Map的Key
T entryValue = entry.getValue(); //获取Map的Value
builder.addFormField(entryKey, valueConverter.convert(entryValue), encoded); //便利整个参数Map依次添加参数值
}
}
@Override void apply(RequestBuilder builder, T value) {
RequestBody body;
body = converter.convert(value); // 转为RequestBody实例
builder.addPart(headers, body);
void addPart(Headers headers, RequestBody body) {
multipartBuilder.addPart(headers, body); //MultipartBody.Builder添加参数
}
@Override void apply(RequestBuilder builder, Map<String, T> value) throws IOException {
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey(); //获取Map的key
T entryValue = entry.getValue(); //获取Map的Value
//为每个文件传输设置头部信息
Headers headers = Headers.of(
"Content-Disposition", "form-data; name=\"" + entryKey + "\"",
"Content-Transfer-Encoding", transferEncoding);
builder.addPart(headers, valueConverter.convert(entryValue));
}
}
void addPart(Headers headers, RequestBody body) {
multipartBuilder.addPart(headers, body);
}
@Override void apply(RequestBuilder builder, T value) {
RequestBody body;
try {
body = converter.convert(value);
builder.setBody(body);
}
void setBody(RequestBody body) {
this.body = body; //设置RequestBody
}
public Request build() {
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
url = baseUrl.resolve(relativeUrl); //设置请求的Url
}
RequestBody body = this.body; //设置请求Body
RequestBody body = this.body;
if (body == null) {
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
requestBuilder.addHeader("Content-Type", contentType.toString()); //设置请求头部信息
}
}
return requestBuilder //利用Okhttp的RequestBuilder创建请求的Request
.url(url)
.method(method, body)
.build();
}
okhttp3.Call call = serviceMethod.callFactory.newCall(request); //调用初始化时设置OkhttpClient创建Call实例
call.execute()
parseResponse(call.execute());
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body(); //获取请求返回Body
rawResponse = rawResponse.newBuilder()
//创建ExceptionCatchingRequestBody实例
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody); // (1)调用ServiceMethod.toResponse()转化响应结果(Gson在此执行映射对象)
return Response.success(body, rawResponse); //(2)返回请求成功,参数:转化后的对象、原来的Response
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}
首先获取ResponseBody,然后调用ServiceMethod.toResponse()转化响应结果(Gson在此执行映射对象),最后返回Reponse
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body); //调用设置的对结果的转换器转换Response
}
ServiceMethod build(){ // 此处的responseConverter
responseConverter = createResponseConverter();
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream()); // 获取JsonReader
try {
return adapter.read(jsonReader); //读取JsonReader转换为对象
} finally {
value.close();
}
}
public static <T> Response<T> success(T body, okhttp3.Response rawResponse) {
。。。。。。
return new Response<>(rawResponse, body, null); // (1)封装转换后的Object和原始的Response
}
* addConverterFactory():为对象的序列化和反序列化添加转换器工厂,上面的converterFactories也是此处添加
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));//保存添加的Converter.Factory
return this;
}
@FormUrlEncoded
@POST("user/register/")
fun register( @Field("repassword") repassword: String): Call<ArticleBean> //返回Call实例
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return call; //默认直接返回RealCall实例
}
};
}
}
serviceMethod.callAdapter.adapt(okHttpCall);
//最终执行nextCallAdapter()
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) { //获取设置的AdapterFcatory
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
}
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
//将添加的Adapter.Factory保存在 adapterFactories集合中
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
@Override public Object adapt(Call<R> call) { //传入的OkhttpCall
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); //对于RxJava此处创建的是BodyObservable
} else {
observable = responseObservable;
}
return observable;
}
//执行被观察者
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
Call<T> call = originalCall.clone(); // (1)Copy一份OKhttpCall
try {
Response<T> response = call.execute(); // (2)执行OKhttpCall完成网络请求和数据转换
if (!call.isCanceled()) {
observer.onNext(response); // (3)发送数据,发送的是封装转化对象和Response的对象
}
}
}
在使用Retrofit时一般设置RxJava2CallAdapter,将创建执行的Call转换为Observable实例,这里直接看adapt()首先根据同步或异步选择相应的被观察者,在被观察者执行时会执行Observable的subscribeActual(),在subscribeActual中执行OKhttpCall完成网络请求和数据转换,然后执行onNext()发送数据
BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream; // 构造函数中保存传入的Observable实例
}
@Override protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new BodyObserver<T>(observer)); //调用保存实力的方法去获取数据
}
Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
observer.onNext(response.body()); // 只发送请求的Body即转换后的对象
}
}
到这里Retrofit的源码分析结束了,总结一下Retrofit的完整执行流程: