Retrofit是一套基于okhttp来封装的网络框架,它的意义在于将okhttp的使用变得更简洁更解耦,其作者JakeWharton是大名鼎鼎的Android开发巨人,ButterKnife,picasso,okhttp,okio等神级项目皆出自他手,所以Retrofit的源码还是很有学习价值的。
废话不多说,先来导入项目依赖:
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
创建一个接口类ServerApi ,先只写一个方法getUserInfo():
public interface ServerApi {
@GET("getInfo")
Call<Result<UserInfo>> getUserInfo();
}
在activity里使用Retrofit来访问接口:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.8.169:8080/OkHttpServer/")//host
.addConverterFactory(GsonConverterFactory.create())//解析转换工厂
.client(new OkHttpClient())//传入OkHttpClient对象
.build();
ServerApi serverApi = retrofit.create(ServerApi.class);//得到ServerApi 的具体实现类对象
Call<Result<UserInfo>> userInfoCall = serverApi.getUserInfo();//得到call
//调用异步方法
userInfoCall.enqueue(new Callback<Result<UserInfo>>() {
@Override
public void onResponse(Call<Result<UserInfo>> call, Response<Result<UserInfo>> response) {
}
@Override
public void onFailure(Call<Result<UserInfo>> call, Throwable t) {
}
});
再重申一下,Retrofit是对okhttp的一个封装, 所以它的核心代码不是网络访问,而是抽离业务代码和功能代码 ,我们看看他是怎么做的。
上面的代码一看就知道关键在于那个create()方法,它把一个接口类变成了一个实例对象:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//重点在这里,利用jdk动态代理返回了接口的实现类对象,动态代理可以单独写一篇文章来研究
//这里只需要知道,接口里的每个方法会执行里面的invoke()方法回调
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.
//如果是object顶级类的方法就直接执行
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//是平台的方法也直接执行
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//这里是解析method的重要方法,主要是各种注解的解析
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//得到一个OkHttpCall,算是okhttp里的realCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//callAdapter如果添加了rxjava的会返回一个observable
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
看看loadServiceMethod()方法:
//这个方法的目的是为了获取ServiceMethod,这个对象封装了这个网络请求方法构建okhttp请求的所有参数
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//一看就是个缓存啦,有就返回缓存的
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
//同步代码里又判断了一次缓存
result = serviceMethodCache.get(method);
if (result == null) {
//新建了一个ServiceMethod,把retrofit和method传进去了
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
来看看ServiceMethod的主要代码:
final class ServiceMethod<R, T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final okhttp3.Call.Factory callFactory;
final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
//builder构建模式
static final class Builder<T, R> {
final Retrofit retrofit;
final Method method;
//方法的注解
final Annotation[] methodAnnotations;
//方法入参的注解,是个二维数组,因为一个入参可能有多个注解
final Annotation[][] parameterAnnotationsArray;
//参数类型数组
final Type[] parameterTypes;
//返回的类型
Type responseType;
//是否拿到了表单
boolean gotField;
//是否拿到了Part
boolean gotPart;
//是否拿到了Body
boolean gotBody;
boolean gotPath;
boolean gotQuery;
boolean gotUrl;
String httpMethod;
boolean hasBody;
boolean isFormEncoded;
boolean isMultipart;
String relativeUrl;
Headers headers;
MediaType contentType;
Set<String> relativeUrlParamNames;//相对路径里的参数,比如{}里的
ParameterHandler<?>[] parameterHandlers;//参数处理器,封装了参数的解析结果
Converter<ResponseBody, T> responseConverter;
CallAdapter<T, R> callAdapter;
//Builder的构造方法
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
//build()方法
public ServiceMethod build() {
//创建一个callAdapter,adapter的作用是把一个类型的东西适配成另一个类型,这里的callAdapter
//就是把okhttp的call转换成你需要的,比如跟rxjava配合使用就需要一个转换成observable的adapter
callAdapter = createCallAdapter();
//返回的response类型,便于解析
responseType = callAdapter.responseType();
//Response类型不被允许
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?");
}
//创建response解析器,这里我们一般用gosn解析
responseConverter = createResponseConverter();
//逐个方法去解析其注解,parseMethodAnnotation字面意思就是解析方法注解
for (Annotation annotation : methodAnnotations) {
//这个方法是核心重点,后面会具体分析,建议先看完这个方法的解析再看后面的代码
parseMethodAnnotation(annotation);
}
//一顿解析之后,开始判空,用多了retrofit应该对这些报错有点印象
if (httpMethod == null) {
//httpMethod 为空,说明你没有写@GET, @POST等网络请求方式注解
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
//Multipart必须要附在有请求体上的请求
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
//表单提交必须要附在有请求体上的请求
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
//parameterCount 表示方法入参的数量,parameterAnnotationsArray是参数的注解
//这是个二维数组,因为参数的注解可能有多个,外层数组是参数,第二层是参数的注解
int parameterCount = parameterAnnotationsArray.length;
//参数的处理,parameterHandlers 也是个数组
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
// 每个参数单独解析,parameterTypes是入参类型的数组,顺序存放
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);
}
//各种判空
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
//得到一个解析好的Method的封装
return new ServiceMethod<>(this);
}
...略
}
...略
}
可以看到在他的Builder的build()方法里做了大量的解析工作,其实主要就是把方法里的那些注解和入参解析成okhttp到时候需要用到的元素。
来看看解析方法注解parseMethodAnnotation(Annotation annotation)方法:
//原来大佬的代码也会有很多if else if - -
// 这里拿到的annotation是网络请求方法上的注解,比如@POST,@GET这些,
//先判断他们是哪种请求,再拿到他们的value,传到
//parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)
//做进一步解析
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;
}
}
最终都走到了parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)方法,这里要明确一个事实,这些方法都是ServiceMethod.Builder类的内部方法,里面涉及到的成员变量都是ServiceMethod.Builder类的:
//解析http方法和路径
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
//此时如果httpMethod 不为空了,报错,只允许注解一个http请求方式
if (this.httpMethod != null) {
throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
//给这些成员变量赋值
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
//确保查询字符串没有任何命名参数
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
//不允许有替代字符创部分,如果要使用动态参数,就使用@Query
//意思是不允许在url拼接动态请求参数{}
throw methodError("URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
//拿到相对url路径
this.relativeUrl = value;
//解析url里的参数名,提取{}里的参数
this.relativeUrlParamNames = parsePathParameters(value);
}
再来看看parseParameter(int p, Type parameterType, Annotation[] annotations)方法:
//解析参数,p代表第几个参数
private ParameterHandler<?> parseParameter( int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
//遍历http相关的注解,有就返回
for (Annotation annotation : annotations) {
//解析参数注解,看看parseParameterAnnotation()方法
ParameterHandler<?> annotationAction = parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
重点方法parseParameterAnnotation() ,有点长,但只是因为对各种类型的注解进行分别处理,其中的逻辑无非是拿到注解的值进行封装,这里只挑QUERY和BODY两个常见的注解来看,:
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Query) {
Query query = (Query) annotation;
String name = query.value();
boolean encoded = query.encoded();
gotQuery = true;
...
//这个converter 的作用在最终构建网络访问的时候会用到,因为是query注解,所以最终给出的肯定是string
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Query<>(name, converter, encoded);
} else if (annotation instanceof Body) {
if (isFormEncoded || isMultipart) {
throw parameterError(p,
"@Body parameters cannot be used with form or multi-part encoding.");
}
if (gotBody) {
throw parameterError(p, "Multiple @Body method annotations found.");
}
//因为是body注解,所以最终给出的是RequestBody
Converter<?, RequestBody> converter;
try {
converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
} catch (RuntimeException e) {
// Wide exception range because factories are user code.
throw parameterError(e, p, "Unable to create @Body converter for %s", type);
}
gotBody = true;
return new ParameterHandler.Body<>(converter);
}
...
return null; // Not a Retrofit annotation.
}
再看看ParameterHandler封装了些什么,同样挑QUERY和BODY的看看:
//ParameterHandler是个接口类,里面有个apply抽象方法
abstract class ParameterHandler<T> {
abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;
//每一种参数注解都有一个对应的实现类,实现apply()方法,处理各自的独特流程
static final class Query<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
//构造方法
Query(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
//这个apply方法最终是在构建请求的时候会用到,看他的入参有个RequestBuilder
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
//这个valueConverter是构造方法传进来的,需要把value转成string
String queryValue = valueConverter.convert(value);
if (queryValue == null) return; // Skip converted but null values
//因为query的参数是string
builder.addQueryParam(name, queryValue, encoded);
}
}
static final class Body<T> extends ParameterHandler<T> {
private final Converter<T, RequestBody> converter;
Body(Converter<T, RequestBody> converter) {
this.converter = converter;
}
@Override void apply(RequestBuilder builder, @Nullable T value) {
if (value == null) {
throw new IllegalArgumentException("Body parameter value must not be null.");
}
RequestBody body;
try {
//转成了requestBody
body = converter.convert(value);
} catch (IOException e) {
throw new RuntimeException("Unable to convert " + value + " to RequestBody", e);
}
//requestBody才是okhttp里body里装的类型
builder.setBody(body);
}
}
}
做下梳理,回到创建动态代理的那个方法:
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);
}
//这里是解析method的重要方法,主要是各种注解的解析
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//得到一个OkHttpCall,算是okhttp里的realCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//callAdapter如果添加了rxjava的会返回一个observable
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
通过loadServiceMethod()方法最终拿到了一个ServiceMethod,这个ServiceMethod里包含通过解析请求方法里拿到的各种封装体,来看看主要是哪些:
final class ServiceMethod<R, T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final okhttp3.Call.Factory callFactory;
final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod; //http访问方式 get还是post等
private final String relativeUrl;//url的相对路径,就是host后面的那些
private final Headers headers;//请求头,可以在方法上通过注解添加
private final MediaType contentType;//传输类型
private final boolean hasBody;//是否有请求体
private final boolean isFormEncoded;//是否是表单提交
private final boolean isMultipart;//是否是多部件提交
private final ParameterHandler<?>[] parameterHandlers;//参数处理详情数组
...
}
至此一个网络请求的方法上的注解和入参都拿到了,再往下是如何访问网络:
//得到一个OkHttpCall,算是okhttp里的realCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//callAdapter如果添加了rxjava的会返回一个observable
return serviceMethod.callAdapter.adapt(okHttpCall);
用ServiceMethod和方法参数值新建了一个OkHttpCall对象,熟悉okhttp的话应该知道这个call是能直接访问网络的,只不过在okhttp里是RealCall,实际上这个OkhttpCall可以说是RealCall的代理类,因为它里面就维护了一个成员变量call,最终可以发现那call是调用了OkhttpClient的newCall方法得到的。
再看serviceMethod.callAdapter.adapt(okHttpCall),serviceMethod的callAdapter是通过createCallAdapter()方法生成的:
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//调用了retrofit的callAdapter
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():
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");
//adapterFactories是Retrofit的变量,如果我们没有
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;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
可以看到最终是在adapterFactories里取的,adapterFactories是adapter工厂集合,如果我们没有添加rxjava的adapter就会返回默认的一个工厂DefaultCallAdapterFactory:
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
//通过它的get方法,拿到一个啥也没干的CallAdapter
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
//最终是调用这个方法,没有任何加工,直接返回入参call
@Override public Call<Object> adapt(Call<Object> call) {
return call;
}
};
}
}
所以每个在serviceApi定义的方法,最终返回的就是一个OkHttpCall,看看OkHttpCall的主要代码:
final class OkHttpCall<T> implements Call<T> {
//这个serviceMethod就是之前做了这么多注解解析得到的
private final ServiceMethod<T, ?> serviceMethod;
//这个方法的入参值
private final @Nullable Object[] args;
private volatile boolean canceled;
@GuardedBy("this")
//这个rawCall,顾名思义原始的call,其实他才是真正去做网络访问的
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this")
private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
@GuardedBy("this")
private boolean executed;
//构造方法
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@Override
//enqueue方法,异步网络请求,okhttp走过一遍的话应该很熟悉
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 {
//这个createRawCall()是关键
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//最终还是调用的rawCall的enqueue()方法
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
//解析response
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();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
private okhttp3.Call createRawCall() throws IOException {
//这个toRequest()把那些解析出来的注解和参数类型转换成request
Request request = serviceMethod.toRequest(args);
//这个serviceMethod.callFactory就是OkHttpClient
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
再来看看那个ServiceMethod的关键方法toRequest(args):
Request toRequest(@Nullable Object... args) throws IOException {
//变形金刚大合体,这些入参都是之前通过解析注解拿到的
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
//ParameterHandler的apply()方法,之前我们分析过的,一个个转成okhttp需要的request参数
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
//最终得到组装好的request
return requestBuilder.build();
}
retrofi的源码到此分析完毕,看完后觉得JakeWharton大神的代码实在是太。。。优雅了,里面涉及到很多设计模式,这些设计模式的运用,让这个看似复杂的okhttp封装变得层次分明,可读性和扩展性都很好,值得反复观摩学习。
最后做个retrofit的总结:
1,核心是运用了jdk动态代理技术,让网络访问中业务代码抽离开,实际的网络访问功能则封装得更容易使用。
2,网络访问的业务代码以接口和注解的形式编写,retrofit则是通过解析注解和参数来构造request。
3,最终每个接口方法返回了一个OkhttpCall,这是个okhttp里RealCall的代理类。
网友评论