基本用法
Retrofit retrofit =new Retrofit.Builder().client(okhttpClient).baseUrl("http://localhost/").addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();
API api=retrofit.create(API.class);
上面代码主要创建了Retrofit对象,并且为Retrofit对象分别设置了OkhttpClient对象、baseUrl、CallAdapterFactory对象和ConvertFactory对象。最关键的是create方法
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);
}
});
}
以上是create方法的全部代码,只有几十行,看着也不是特别复杂。第一行 Utils.validateServiceInterface(service);从名字就可以知道是用来检验参数service是否是一个接口的,不是重点,不需要重点关注。第二行validateEagerly默认是false,所以第三行不会执行,(注:如果我们在构建Retrofit对象时设置了validateEagerly属性为true,那么第三行eagerlyValidateMethods(service)会执行,这个方法中会遍历接口中所有的方法,如果不是default方法,就调用loadServiceMethod方法,将接口中的所有方法缓存,default方法是jdk1.8当中引入的,在jdk1.8当中接口可以有实现方法,只要在方法前加default关键字)。在create方法的第五行就直接返回了一个动态代理对象,也就是说create方法实际就做了两件事,第一、验证参数是不是接口类型,第二、返回代理对象。那么重点关注的代码都在代理对象里面了。Proxy.newProxyInstance方法返回一个实现了参数service接口的对象,也就是开头 API api=retrofit.create(API.class)中的api对象。根据动态代理的特性,我们每次调用api这个对象的方法,其实调用的是InvocationHandler当中的invoke方法,也就是create方法当中第七行的new InvocationHandler()对象中的invoke方法。在invoke方法当中首先验证了方法是否是Object的方法,如果是,就直接调用并返回了。然后判断方法是否是默认方法,如果是,也直接返回了。那么重点就在最后四行代码当中了。
loadServiceMehod方法分析
在create方法的倒数第四行调用了Retrofit的loadServiceMethod方法,该方法传入method参数返回了一个ServiceMethod对象。下面是loadServiceMethod方法的源码
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;
}
这个方法也很简单,首先判断缓存当中有没有method对应的ServiceMethod对象,如果有就返回该对象,没有就创建对象并将其放入缓存。在构建ServiceMethod对象时传入了retrofit对象和method对象。
创建OkHttpCall对象
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
OkHttpCall对象的构造方法很简单,仅仅是对两个属性赋值而已。到目前为止还没有看到一行关于网络请求的代码,那么网络请求的代码应该是在create方法最后一行当中了。
CallAdapter的adapt方法
在Retrofit的create方法最后一行调用了ServiceMethod的callAdapter的adapt方法。ServiceMethod的CallAdapter对象是通过Retrofit中设置的CallAdapterFactoty对象创建出来的,我设置的是RxJava2CallAdapterFactory,那主要的网络请求逻辑应该是在RxJava2CallAdapterFactory里面了。
RxJava2CallAdapterFactory的get方法
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, false, true, false, false, false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable" : isSingle ? "Single" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
该方法返回一个CallAdapter对象,也就是ServiceMethod中的CallAdapter对象。首先分析一下该对象的创建过程。该方法首先判断我们调用的接口方法的返回值类型,返回值类型必须是Completable,Observable,Flowable,Single,Maybe中的一种,否则会返回null。判断完返回类型接着判断返回类型的泛型,最后返回一个RxJava2CallAdapter对象。
RxJava2CallAdapter的adapt方法
@Override public <R> Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = new CallObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
这个方法主要根据接口方法返回值的类型和泛型类型返回不同的Observable,如果返回值泛型是Result类型,返回ResultObservable,如果是返回值泛型是Response类型,返回responseObservable,如果是自定义的类型则返回BodyObservable。到目前为止还是没有发现网络请求相关的代码,那么网络请求的代码应该是在Observable里面了。平时请求一般都是自定义类型,那么主要看一下Observable当中的逻辑。
CallObservable
final class CallObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
observer.onSubscribe(new CallDisposable(call));
boolean terminated = false;
try {
Response<T> response = call.execute();
if (!call.isCanceled()) {
observer.onNext(response);
}
if (!call.isCanceled()) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!call.isCanceled()) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
private static final class CallDisposable implements Disposable {
private final Call<?> call;
CallDisposable(Call<?> call) {
this.call = call;
}
@Override public void dispose() {
call.cancel();
}
@Override public boolean isDisposed() {
return call.isCanceled();
}
}
}
CallObservable中有一个Call对象的引用,这个对象就是在Retrofit的create方法当中的 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args)这个okHttpCall对象。在CallObservable的subscribeActual方法当中执行了call.execute(),这行代码返回了一个Response(注:这个Response类是Retrofit包当中的,并非OkHttp当中的)对象,那网络请求的代码应该是在这个方法中执行。
OkHttpCall的execute方法
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
这个方法的逻辑很简单,首先创建一个okhttp3.Call对象,然后执行call.execute方法,最后将okhttp当中的Response类型转换为Retrofit当中的Response对象。
OkHttpCall的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) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
这个方法的主要逻辑就是根据不同的http响应码返回不同的Retrofit.Response。如果是正常的200响应码,会走最后这个return语句。返回一个Retrofit.Response对象,该对象封装了一个泛型类型的body和一个OkHttp.Response对象,这个泛型对象时通过ServiceMethod的toResponse方法返回的,在toResponse方法当中会调用Converter的convert方法,也就是在创建Retrofit的时候设置的ConvertFactory创建出来的Convert,通常是设置GsonConvert,也就是将网络请求的响应体解析成接口方法泛型里面的类型。
BodyObservable
final class BodyObservable<T> extends Observable<T> {
private final Observable<Response<T>> upstream;
BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}
@Override protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new BodyObserver<>(observer));
}
private static class BodyObserver<R> implements Observer<Response<R>> {
private final Observer<? super R> observer;
private boolean terminated;
BodyObserver(Observer<? super R> observer) {
this.observer = observer;
}
@Override public void onSubscribe(Disposable disposable) {
observer.onSubscribe(disposable);
}
@Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
observer.onNext(response.body());
} else {
terminated = true;
Throwable t = new HttpException(response);
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
@Override public void onComplete() {
if (!terminated) {
observer.onComplete();
}
}
@Override public void onError(Throwable throwable) {
if (!terminated) {
observer.onError(throwable);
} else {
// This should never happen! onNext handles and forwards errors automatically.
Throwable broken = new AssertionError(
"This should never happen! Report as a bug with the full stacktrace.");
//noinspection UnnecessaryInitCause Two-arg AssertionError constructor is 1.7+ only.
broken.initCause(throwable);
RxJavaPlugins.onError(broken);
}
}
}
}
前面这些网络请求,响应解析功能都是在CallObservable当中完成的,但最终返回给我们用的却是BodyObservable,BodyObservable对CallObservable做了一次封装,onNext只传了Retrofit.Response的body对象,也就时Gson解析出来的对象。这样就只能得到响应体,某些时候需要用到响应头,可以将接口方法的返回值的泛型使用Retrofit.Response就可以了。
总结
1.创建Retrofit对象。
2.调用Retrofit对象的create方法返回动态代理对象。
3.调用动态代理对象的方法。
4.调用CallAdapter的adapt方法,返回一个Observable对象。
5.在Observable对象subscribe方法当中进行网络请求和响应体的解析。
(注:省略了根据接口方法注解生成Request部分)
网友评论