如何使用retrofit
1.引入库
compile 'com.squareup.retrofit2:retrofit:2.0.2'
复制代码
2. 使用流程
retrofit在使用的过程中,需要定义一个接口对象
public @interface ApiService{
@GET("/users/{username}")
Call<User> getUser (@Path("username") String username);
@POST
Call<List<User>> addUser(@Body User user);
}复制代码
3. 创建retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.client(OkHttpClient)//配置OKhttp客户端
.baseUrl("http://www.example.com")
.addConverterFactory(GsonConverterFactory.create())
.validateEagerly() //在Call时,是否立即验证接口中的方法配置
.callbackExecutor() //回调
.build();ApiService service = retrofit.create(ApiService.class);
复制代码
4. 创建接口实例
Call<User> user = service.getUser("test");复制代码
5. 发起请求
user.enqueue(new Callback<List<User>>()
{
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response)
{
Log.e(TAG, "normalGet:" + response.body() + "");
}
@Override
public void onFailure(Call<List<User>> call, Throwable t)
{
}
});
复制代码
源码解析
1. 接口实例是如何拿到的
先来看下build方法,返回了Retrofit实例,参数是传入的值,若没有,使用默认的
public Retrofit build() {
//...
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);
}复制代码
下一步,调用create 发生了什么?
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service); //验证传入的class是否声明为interface
if (validateEagerly) { //是否立即验证接口中的方法配置,如果true,最终调用loadServiceMethod
eagerlyValidateMethods(service);
}
//如何理解Proxy.newProxyInstance???看后面
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 serviceMethod = loadServiceMethod(method);
//返回OkHttpCall对象
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//最后返回适配以后的Call,比如添加Rxjava适配,则返回Observe对象
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}复制代码
2. 如何理解Proxy.newProxyInstance
先看一个例子
public interface ITest{
@GET("/heiheihei")
public void add(int a, int b);
}
public static void main(String[] args){
ITest iTest = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(), new Class<?>[]{ITest.class}, new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
Integer a = (Integer) args[0];
Integer b = (Integer) args[1];
System.out.println("方法名:" + method.getName());
System.out.println("参数:" + a + " , " + b);
GET get = method.getAnnotation(GET.class);
System.out.println("注解:" + get.value());
return null;
}
});
iTest.add(3, 5);
}
复制代码
运行结果是:
方法名:add
参数:3 , 5
注解:/heiheihei
复制代码
可以看到我们通过Proxy.newProxyInstance
产生的代理类,当调用接口的任何方法时,都会调用InvocationHandler#invoke
方法,在这个方法中可以拿到传入的参数,注解等。
上面retrofit create的实现中,最后同样使用了Proxy
这个类的API,然后在invoke
方法里面拿到足够的信息去构建最终返回的Call。
这里一开始没看懂 Proxy.newProxyInstance 作用,参考了blog.csdn.net/lmj62356579…
3. OkHttpCall对象的生成
过程很简单
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
复制代码
4. 如何拿到接口方法传入的参数,注解
这一步通过loadServiceMethod 来实现
serviceMethodCache是一个LinkedHashMap,会先从serviceMethodCache缓存里面取,若为NULL则重新构造一个ServiceMethod对象,并返回
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//关键代码,干了什么
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}复制代码
下面看下new ServiceMethod.Builder(this, method).build(); 具体工作
//返回接口定义的方法的相关信息
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations(); //方法的注解, @GET @POST等
this.parameterTypes = method.getGenericParameterTypes();//参数类型
this.parameterAnnotationsArray = method.getParameterAnnotations(); //参数的注解 @Path @Body等
}复制代码
build的具体工作
public ServiceMethod build() {
callAdapter = createCallAdapter(); //call的适配, 很重要, 最后由它发起最终请求
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);
}
//略...
return new ServiceMethod<>(this);
}复制代码
parseMethodAnnotation(annotation); 把所有你加上的注解及及值提取出来
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);
}
//略....
}复制代码
5. http请求是如何发送出去的?
在Retrofit的create方法,最后返回了serviceMethod.callAdapter.adapt(okHttpCall);
这个callAdapter最终拿到的是我们在构建retrofit里面时adapterFactories时添加的,即为:new ExecutorCallbackCall<>(callbackExecutor, call)
,该ExecutorCallbackCall
唯一做的事情就是将原本call的回调转发至UI线程。
public ServiceMethod build() {
callAdapter = createCallAdapter(); //call的适配, 很重要, 最后由它发起最终请求
//...
return new ServiceMethod<>(this);
}复制代码
ServiceMethod.java
private CallAdapter<?> createCallAdapter() {
Type returnType = method.getGenericReturnType();
//...
Annotation[] annotations = method.getAnnotations();
try {
return 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.java
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(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;
}
}
//....
}复制代码
最后调用ExecutorCallAdapterFactory的get方法
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
//调用它
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}复制代码
可以看到adapt
返回的是ExecutorCallbackCall
对象,继续往下看:
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;
}
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
}复制代码
可以看出ExecutorCallbackCall仅仅是对Call对象进行封装,类似装饰者模式,只不过将其执行时的回调通过callbackExecutor进行回调到UI线程中去了。
其实我们在写代码时拿到的call对象就是ExecutorCallbackCall对象,最后一般会执行enqueue
方法,看下具体实现
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}复制代码
delegate就是构建ExecutorCallbackCall时传入的OkHttpCall对象,因此会调用OkHttpCall的enqueue,看下实现
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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) {
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 {
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();
}
}
});
}复制代码
整个流程就是创建okhttp3.Call对象,并进一步调用其enqueue方法,okhttp3.Call的创建通过
createRawCall方法
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.toRequest
实现了ServiceMethod到Request的转换,接着通过request去构造call对象,然后返回.
构建Request的过程很简单,就是把从把从ServiceMethod得到的参数传入RequestBuilder和RequestBody
还有一个问题是,对于网络返回的数据怎么转换成我们想要的类型?
同样在okhttp3.Call中enqueue的请求成功回调中 parseResponse(rawResponse)
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);
}复制代码
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) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}复制代码
可以看到最后通过serviceMethod对ResponseBody进行转化,然后返回,转化实际上就是通过responseConverter
的convert方法。
ServiceMethod.java
/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}复制代码
6. Converter.Factory
Converter.Factory用于将返回的数据解析成指定的类型,基本使用如下
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.build();
复制代码
GsonConverterFactory需要引入,它是Converter.Factory factory
对象的具体实现
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:converter-gson:2.0.2';
复制代码
看下Converter.Factory factory
源码
public interface Converter<F, T> {
T convert(F value) throws IOException;
/** Creates {@link Converter} instances based on a type and target usage. */
abstract class Factory {
/**
* Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for
* response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
* declaration.
*/
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
* values.
*/
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
}复制代码
Factory是个抽象类,有三个非抽象方法,我们自定义时可以根据需要选择实现。
下面看下squareup官方的GsonConverterFactory的实现
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}复制代码
看着挺简单的。。。以后再写
7.总结
- 首先构造retrofit实例,根据需要传入baseurl,callFactory, client(默认okhttpclient),converterFactories,adapterFactories,excallbackExecutor。
- 然后通过create方法拿到接口的实现类
- 调用接口方法时,进入Proxy的invoke方法内部,拿到我们所声明的注解以及实参等,构造ServiceMethod,ServiceMethod中解析了大量的信息,最痛可以通过
toRequest
构造出okhttp3.Request
对象。有了okhttp3.Request
对象就可以很自然的构建出okhttp3.call
,最后calladapter对Call进行装饰返回。 - 拿到Call就可以执行enqueue或者execute方法了