The project is now used in the Retrofit for network requests, so I spent some time analyzing its source code, now do a brief analysis.
Overall, Retrofit uses dynamic proxy mode, it is not a final request to the network, the network is a real request OkHttp. Here, do not do a detailed analysis, I plan a reanalysis next.
Take a look at its overall flow
We look at the normal use Retrofit, then combined on chart analysis.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(sOkHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
This is normal configuration
1. In the source Retrofit.Buidler () in
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 根据 platform, 选择不同的 CallbackExecutor
// 这里是 platform 是 Android , 返回的是 MainThreadExecutor;
// MainThreadExecutor 类,内部是通过 Handler 将 Runnable post 回主线程执行
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// adaperFactories 是用来在存放 CallAdapterFactory, 例如使用 RxJavaCallAdapterFactory, 也会添加进来
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//defaultCallAdapterFactory 是 ExecutorCallAdapterFactory,其中 MainThreadExcutor 作为参数构造
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);
}
Detailed analysis see the comment;
2. Retrofit.create()
Using dynamic proxy mode In this method, see the proxy mode and the dynamic proxy mode ,
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 动态代理, 返回一个 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);
}
// 默认是 false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy,
args);
}
// ServiceMethod 调用接口的方法,转变成一个 Http Call
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// serviceMethod.callAdapter 返回是 默认ExecutorCallAdapterFactory
// &ExecutorCallbackCall
// 如果添加了 RxJavaCallAdapter, 返回的是 RxJavaCallAdapter
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
3. ServiceMethod.build()
The main job of the three-point method
- Retrofit.build removed in CallAdapter, for example, is arranged above RxJavaCallAdapterFactory, the resultant is RxJavaCallAdapter;
- Retrofit.build taken in responseConverter, for example, is arranged above GsonConverterFactory, is obtained GsonResponseBodyConverter.
- Notes analytical method
public ServiceMethod build() {
// 创建 CallAdapter, 其实是返回 Retrofit 中的 callAdapter,
// ExecutorCallAdapterFactory$ExecutorCallbackCall
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
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?");
}
// 返回 Retrofit.responseBodyConverter(...), 其实是从 converterFactories 中取出 ResponseBodyConverter
// 例如,如果配置了 GsonResponseBodyConverter, 则返回.
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
// 解析注解方法,
//@GET("group/{id}/users")
//Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
// 中的 @GET("group/{id}/users")
parseMethodAnnotation(annotation);
}
// 省略后面
....
}
Retrofit of execution
performing a synchronous method call and an asynchronous method
synchronous call.execute ()
Asynchronous call.enqueue (Callback callback);
here synchronized Example
1. OkHttpCall.execute
// 同步执行
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
// 省略
...
call = rawCall;
if (call == null) {
try {
// 创建 Call
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
// 发起请求,并解析返回结果
// 这里的 call 是 OkHttp 中的 RealCall
return parseResponse(call.execute());
}
2. OkHttpCall.createRawCall
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
// 返回的是 RealCall
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
3. OkHttCall.parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// 省略
....
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
// T 是想要的结果,例如 Call<List<Repo>> listRepos(@Path("user")
// String user); 中的 List<Repo>
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// 省略
...
}
}
3. ServiceMethod.toResponse
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
// responseConverter 是 Retrofit 中配置的 Conveter
return responseConverter.convert(body);
}
Examples of the above configuration is Conveter GsonConverter, therefore, resonseConverter here is GsonResponseConverter.
If we convert Http results returned Java objects you want, we must implement the Converter interface, but also to achieve RequestConverter and ReponseConverter specific implementations Gson conversion method may reference source.
At this point, Retrofit basic source code analysis is complete.
Comment has been uploaded to GitHub RetrofitAnnotions
Personally I think a lot of knowledge can be learned:
Retrofit using Build mode, in fact, many have used the open source library, you can look at specific "Effective Java" in the relevant section, which has detailed description;
Retrofit using the constructor Collection.unmodifiableList (list) method, such a return may traverse the List only, but can not be modified List;
It uses dynamic proxy mode;
Detect whether a class is Interface, you can call class.isInterface.
utils.java in
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
** Reference Articles
these articles are good, it is recommended to see. **