1 前言
本文从流程的角度分析了Rtrofit
的请求以及回调过程,对代码结构会有一个比较清晰的认知,具体的功能并没有跟进去。这样子的好处是不至于由于某个或者某几个具体功能的解析而使得整个思绪变得混乱。下一篇会对各个具体的功能各个击破,比如说注解解析等。
2 构建Retrofit对象
Rtrofit
的一大特色就是可以配置各种工厂。比如说RxJavaCallAdapterFactory
那么结果便可以生成Observer对象,你就可以方便的使用Rxjava
来处理数据了。再比如说你也可以用protobuf
或者gson
来转换数据。具体支持对象可以看源码目录:
首先看下一个简单的例子:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
这是典型的建造者模式。首先通过Builder()来生成不同平台的对象这是程序自动完成的。
这边没有指定okhhtpclient
,那么他内部会自动生成一个新的。
接下来就是三个比较常用的配置。
首先是指定baseURL
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));//步骤1
}
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();//步骤2
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
首先看到步骤1的HttpUrl.get(baseUrl)
,这个是将字符串转成okhttp
能够识别的HttpUrl
。
跟进baseUrl
方法看下步骤2,这边首先是从baseUrl
中得到不同的碎片。接下来就是检测最后一个碎片是不是“/”。如果不是的话则报错。
最后就将baseUrl
保存起来。那么baseUrl
完成了。
其次添加转换工厂addConverterFactory(GsonConverterFactory.create())
这边逻辑比较简单也就是将GsonConverterFactory
工厂对象存入converterFactories
。
接着添加addCallAdapterFactory(RxJavaCallAdapterFactory.create())
这个也比较简单,将RxJavaCallAdapterFactory
工厂对象存入callAdapterFactories
中去。
最后通过build()整合之前的配置生成Retrofit对象,如下所示。
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();//如果没有传如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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);//先添加外部传入的转换器
converterFactories.addAll(platform.defaultConverterFactories());//最后添加默认转换器
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List<Converter.Factory> converterFactories,
List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor,
boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
3 网络请求与回调流程分析
上面的例子可以看到,只要调用create就可以自动生成对应的对象。这边使用的是动态代理,内部封装了各种底层调用而调用者是毫无感知的。以下是动态代理的代码。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable 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) {//步骤1
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)//步骤2
: loadServiceMethod(method).invoke(args);
}
});
}
这边排除了非接口两种情况:
/步骤1:当该方法所在的类是继承于Object,也就是说该方法已经实现不用代理了。那么按正常的模式调用返回。
步骤2:如果是java8
中的新特性,即interface有个默认实现的方法。那么也是按正常的模式调用返回。
所以重点就在于loadServiceMethod(method).invoke(args)
,它生成一个ServiceMethod
对象,执行对应的方法后返回结果。
那么现在来分析一下loadServiceMethod(method).invoke(args)
功能。
首先是loadServiceMethod(method)
跟进去看下代码:
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);//步骤1
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);//步骤2
serviceMethodCache.put(method, result);
}
}
return result;
}
步骤1:先去缓存看下有没有现成的ServiceMethod
,有的话直接拿出来用。
步骤2:通过传进来的method以及Retrofi
对象来构建ServiceMethod
对象。那么ServiceMethod
对象就构建完成了。
接下来看看ServiceMethod.parseAnnotations(this, method)
:
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
...
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
通过retrofit, method生成requestFactory
,然后HttpServiceMethod.parseAnnotations
调用这三个参数生成HttpServiceMethod
对象。
综上所述,loadServiceMethod(method)
生成了HttpServiceMethod
对象。这个对象里包含了requestFactory,callFactory,responseConverter
等各种网络请求相关的工厂。
接下来调用invoke(args)
生成执行结果。这边以Rxjava
为例子,执行的结果是Obeserver
观察者对象。那么跟进去看下。
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
先生成一个OkHttpCall
对象,它可以看成是Okttp.call
的包装类,也是一个百宝箱。
继续看下去adapt(call, args)
,它是一个抽象的方法:
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
回到oadServiceMethod(method)
,它生成的HttpServiceMethod
对象肯定实现了该adapt。
之前分析是HttpServiceMethod
的parseAnnotations
方法最终生成HttpServiceMethod
对象。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
由上可知他们返回CallAdapted
或SuspendForResponse
或SuspendForBody
对象,列出他们的代码:
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
...
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
...
@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
...
}
}
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
...
@Override
protected Object adapt(Call<ResponseT> call, Object[] args) {
call = callAdapter.adapt(call);
...
}
}
可知他们都继承于HttpServiceMethod
,则必定实现了adapt
。所以最终是调用了callAdapter
的adapt
方法。这边用的例子是Rxjava
所以callAdapter
即RxJavaCallAdapter
。所以invoke(args)
最终调用的是RxJavaCallAdapter
的adapter
方法:
@Override
public Object adapt(Call<R> call) {
OnSubscribe<Response<R>> callFunc =
isAsync ? new CallEnqueueOnSubscribe<>(call) : new CallExecuteOnSubscribe<>(call);
...
}
这边的call即我们之前生成的OkHttpCall
,它包含了Rtrofit
构建时候传进的各种解析工厂,网络请求工厂,Method以及参数等各种网络请求相关数据。
先看callFunc
这个变量,它分为异步和同步两种情况,大相径庭。这边只分析同步的情况,直接看CallExecuteOnSubscribe
的call方法:
@Override
public void call(Subscriber<? super Response<T>> subscriber) {
// Since Call is a one-shot type, clone it for each new subscriber.
Call<T> call = originalCall.clone();
CallArbiter<T> arbiter = new CallArbiter<>(call, subscriber);//步骤1
subscriber.add(arbiter);
subscriber.setProducer(arbiter);
Response<T> response;
try {
response = call.execute();//步骤2
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
arbiter.emitError(t);
return;
}
arbiter.emitResponse(response);//步骤3
}
步骤1:new
出一个CallArbiter
对象,它是call(OkHttp)
以及subscriber的包装类。
步骤2:这边是真正开始执行网络请求的地方,接下来再分析。
步骤3:arbiter.emitResponse(response)
,也就是网络请求完之后开始发射结果。跟进去看下:
void emitResponse(Response<T> response) {
while (true) {
int state = get();
switch (state) {
case STATE_WAITING:
...
break; // State transition failed. Try again.
case STATE_REQUESTED:
if (compareAndSet(STATE_REQUESTED, STATE_TERMINATED)) {
deliverResponse(response);
return;
}
break; // State transition failed. Try again.
case STATE_HAS_RESPONSE:
case STATE_TERMINATED:
throw new AssertionError();
default:
throw new IllegalStateException("Unknown state: " + state);
}
}
}
这边主要是看下STATE_REQUESTED的情况,他会调用deliverResponse(response)
方法,跟进去看下。
private void deliverResponse(Response<T> response) {
try {
if (!isUnsubscribed()) {
subscriber.onNext(response);//步骤1
}
} catch (OnCompletedFailedException
...
return;
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
try {
subscriber.onError(t);
} catch (OnCompletedFailedException
...
} catch (Throwable inner) {
...
}
return;
}
try {
if (!isUnsubscribed()) {
subscriber.onCompleted();//步骤2
}
} catch (OnCompletedFailedException
| OnErrorFailedException
| OnErrorNotImplementedException e) {
...
} catch (Throwable t) {
...
}
}
步骤1开始向Rxjava
观察者发送数据,步骤2通知Rxjava
观察者发送完成。到这边Retrofit的调用者即可收到网络请求收到的数据了。
回过去再看看OkHttpCall
的call方法中response = call.execute()
。看看里面到底是怎么执行网络请求的。
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = getRawCall();//步骤1
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());//步骤2
}
private okhttp3.Call getRawCall() throws IOException {
okhttp3.Call call = rawCall;
...
// Create and remember either the success or the failure.
try {
return rawCall = createRawCall();
} catch (RuntimeException | Error | IOException e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
...
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(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;
}
}
步骤1:call
是Okttp
的call
,看看他怎么获取的。getRawCall() <-- createRawCall() <-- callFactory.newCall(requestFactory.create(args))
步骤2:parseResponse(call.execute()) <-- responseConverter.convert(catchingBody)
两个步骤完成了网络数据的请求,转换,请求参数的解析等。这边想要说明的是OkHttp
这个类十分重要也是网络请求的直接执行者,他内部包含了requestFactory,responseConverter,callFactory(OkHttp)
等一系列工厂以及args
等数据。下一篇将对网络请求过程进行具体解析。
这边回到RxJavaCallAdapter
的adapter方法。
@Override
public Object adapt(Call<R> call) {
OnSubscribe<Response<R>> callFunc =
isAsync ? new CallEnqueueOnSubscribe<>(call) : new CallExecuteOnSubscribe<>(call);
OnSubscribe<?> func;
if (isResult) {
func = new ResultOnSubscribe<>(callFunc);
} else if (isBody) {
//对请求做进一步封装,这边的意思是是只回调内容本身。并不包括Response
func = new BodyOnSubscribe<>(callFunc);
} else {
func = callFunc;
}
Observable<?> observable = Observable.create(func);//步骤1
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isSingle) {
return observable.toSingle();
}
if (isCompletable) {
return observable.toCompletable();
}
return observable;
}
步骤1调用Observable.create(func)
创建一个被观察者返回给动态代理的调用者,只要他被订阅那么func
就会执行也就是网络请求会被执行。
observable//上面动态代理返回的Observable
.subscribeOn(Schedulers.io()) // 在子线程中进行Http访问
.observeOn(AndroidSchedulers.mainThread()) // UI线程处理返回接口
.subscribe( // 一旦订阅那么网络请求就开始执行
new Observer<PostInfo>() {
@Override
public void onCompleted() {
//返回完成状态
}
@Override
public void onError(Throwable e) {
//返回错误
}
@Override
public void onNext(PostInfo postInfo) {
//返回数据
}
});
至此,从Retrofit
创建到Rxjava
接收到数据的流程分析完毕。
流程可以总结如下:
Rtrofit
(动态代理) --> HttpServiceMethod
--> OkHttpCall
--> RxJavaCallAdapter
--> Observable(被观察者)
当Observable观察者订阅的时候,那么就会调用OkHttpCall
执行网络请求并返回结果。