一開(kāi)始的目的是為了學(xué)習(xí)動(dòng)態(tài)代理的使用,后來(lái)干脆把整個(gè)流程梳理了下
這不是完整的Retrofit
厅翔,是純Java
環(huán)境下不涉及Android,Http
的流程代碼,Retrofit
的精簡(jiǎn)代碼凌那,把內(nèi)部一些設(shè)計(jì)和邏輯做了精簡(jiǎn)阻问,主要是為了學(xué)習(xí)整個(gè)代碼的大體設(shè)計(jì)和流程
Retrofit
內(nèi)關(guān)于OkHttp、Rx部默、Android
相關(guān)的部分都去除了侵蒙,其中okhttp3.call
由一個(gè)RawCall
來(lái)代替,內(nèi)部沒(méi)有做相關(guān)網(wǎng)絡(luò)請(qǐng)求傅蹂,只是做了下字符串拼接后println()
纷闺,盡量還保持著Retrofit
原有的類,有些地方份蝴,把注釋也給粘貼過(guò)來(lái)了
Demo完整代碼——>GitHub RetrofitDemo
1. Demo
使用也基本Retrofit
的形式犁功,Demo
本身并無(wú)任何意義
1.1 Service
/** 獲取幣種Coin Service 接口 */
public interface IBtcService {
/** 獲取 BTC 信息 */
Call<String> getBtcCoinInfo(@Content String content);
}
@Content
是自己定義的一個(gè)注解掀宋,表明方法內(nèi)是Content
,作用類比@Path
等硼一,支持多個(gè)不同類型的Content
,例如
getBtcCoinInfo(@Content String content1, @Content int content2)
返回類型必須是Call<>
1.2 使用
public class RetrofitDemo {
public static void main(String[] args) {
btcInfo();
}
/** BTC 信息 */
private static void btcInfo() {
Retrofit retrofit = new Retrofit.Builder().build();
IBtcService iBtcService = retrofit.create(IBtcService.class);
Call<String> call = iBtcService.getBtcCoinInfo("BTC $3512.6 ");
try {
Response<String> response = call.execute();
System.out.println(response.body());
} catch (IOException e) {
e.printStackTrace();
}
}
}
結(jié)果就是Content
前拼接當(dāng)前時(shí)間
2019-1-27 12:01:27
BTC $3512.6
2. 流程
基于Retrofit2.5.0
版本如失,整個(gè)流程的代碼都在core
文件夾下
整個(gè)流程涉及有4個(gè)重要部分Retrofit,CallAdapter,Converter,OkHttpCall
Retrofit
作為門面案糙,關(guān)鍵點(diǎn)之一是crete()
方法限嫌,使用動(dòng)態(tài)代理通過(guò)CallAdatper
將Retrofit.Call
轉(zhuǎn)換為一個(gè)Service
Converter
轉(zhuǎn)換器,Request Body
和Response Body
都要用
OkHttpCall
侍筛,在實(shí)際的Retrofit
中萤皂,持有著一個(gè)OkHttp3.Call
,最終所有的有關(guān)網(wǎng)絡(luò)請(qǐng)求的操作匣椰,都會(huì)在這里執(zhí)行裆熙。由于我這里將網(wǎng)絡(luò)請(qǐng)求去掉做精簡(jiǎn),只是調(diào)用了RawCall.execute()
來(lái)模擬網(wǎng)絡(luò)請(qǐng)求
注意:
還有一個(gè)重要的東西CallbackExecutor
,給精簡(jiǎn)去掉了入录。在Android
內(nèi)蛤奥,由于UI線程
的原因,網(wǎng)絡(luò)請(qǐng)求時(shí)OkHttp
會(huì)通過(guò)線程池運(yùn)行在單獨(dú)線程中僚稿,但本Demo
為了簡(jiǎn)化流程凡桥,就網(wǎng)絡(luò)請(qǐng)求模擬時(shí),沒(méi)有新創(chuàng)建線程蚀同, 對(duì)整個(gè)流程學(xué)習(xí)影響不大
實(shí)際在Retrofit
中缅刽,Android
環(huán)境默認(rèn)情況下,會(huì)用一個(gè)Handler
進(jìn)行線程間通信將Response
回調(diào)到UI
線程
2.1 build()構(gòu)建
Retrofit
構(gòu)造方法并不是private
的蠢络,但一般都是通過(guò)內(nèi)部的Builder
來(lái)構(gòu)建
@Nullable
private Executor callbackExecutor;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
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> 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(converterFactories, callAdapterFactories);
}
Executor
可以先不關(guān)注
CallAdapter
作用就是將Call
轉(zhuǎn)換為Service
,默認(rèn)情況下使用DefaultCallAdapterFactory
Converter
轉(zhuǎn)換器衰猛,默認(rèn)情況下,使用BuiltInConverters
來(lái)構(gòu)建內(nèi)置的轉(zhuǎn)換器
在調(diào)用build()
后刹孔,Retrofit
就有了關(guān)聯(lián)的CallAdapterFactory啡省、ConveterFactory
,但此時(shí)具體要使用的CallAdpater髓霞、Converter
還不知道
2.2 動(dòng)態(tài)代理
Retrofit
作為門面卦睹,關(guān)鍵點(diǎn)之一是crete()
方法,使用動(dòng)態(tài)代理通過(guò)CallAdatper
將Retrofit.Call
轉(zhuǎn)換為一個(gè)Service
/**
* 利用 JDK 動(dòng)態(tài)代理方库,create 出一個(gè) T(Service)
* <p>
* 需要將 Call 通過(guò) CallAdapter 轉(zhuǎn)換成 T
* <p>
* Single-interface proxy creation guarded by parameter safety
*
* @param service 代理接口 Class
* @param <T> 代理
* @return T, 代理 Service
*/
@SuppressWarnings("unchecked")
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
new InvocationHandler() {
private final Object[] emptyArgs = new Object[0];
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
loadServiceMethod()
從已創(chuàng)建的mServiceCache
中獲取當(dāng)前方法對(duì)應(yīng)的ServiceMethod
结序,沒(méi)有就創(chuàng)建一個(gè)新的put
進(jìn)去
private ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = mServiceCache.get(method);
if (result != null) {
return result;
}
synchronized (mServiceCache) {
result = mServiceCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
mServiceCache.put(method, result);
}
}
return result;
}
2.2.1 ServiceMethod
ServiceMethod
是一個(gè)抽象類,有一個(gè)HttpSeeviceMethod
子類薪捍,負(fù)責(zé)將好的Request,CallAdapter,Converter
組合起來(lái)
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract T invoke(Object[] args);
}
parseAnnotations()
內(nèi)笼痹,首先會(huì)通過(guò)RequestFactory.parseAnnotations()
進(jìn)行解析注解配喳,然后構(gòu)建出一個(gè)RequestFactory
再判斷returnType
返回類型酪穿,若為void
,就會(huì)拋出異常晴裹,也就是創(chuàng)建的Service
接口返回值不能為void
返回值為子類HttpServiceMethod
的parseAnnotations()
方法返回值
HttpServiceMethod
內(nèi)部主要有兩個(gè)方法:
/** 構(gòu)建具體的 CallAdapter被济,Response Converter */
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 創(chuàng)建 CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
// Response Converter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
return new HttpServiceMethod<>(requestFactory, callAdapter, responseConverter);
}
/** ServiceMehod 抽象方法,將OkHttpCall進(jìn)行適配*/
@Override
ReturnT invoke(Object[] args) {
return mCallAdapter.adapt(new OkHttpCall<>(mRequestFactory, args, mResponseConverter));
}
到了此時(shí)涧团,具體要使用的CallApdater只磷、Converter
都已經(jīng)創(chuàng)建好,就等著調(diào)用Service
內(nèi)的方法進(jìn)行網(wǎng)絡(luò)請(qǐng)求
mCallAdapter.adapt()
泌绣,就是適配器模式钮追,將Service
適配成Call
2.3 Converter 轉(zhuǎn)換器
Converter<F,T>
是一個(gè)接口,將一個(gè)F -> T
兩個(gè)地方要用阿迈,Request Body
以及Response Body
Request Body
需要解析注解元媚,拿到注解的信息拼裝用于網(wǎng)絡(luò)請(qǐng)求的Request
Response Body
就是將Json
轉(zhuǎn)換成為Bean
,但Demo
里這里簡(jiǎn)化了,只是直接將字符串進(jìn)行返回
2.3.1 解析 Request Body 注解
在ServiceMethod.parseAnnotations()
內(nèi)刊棕,RequestFactory.parseAnnotations()
時(shí)會(huì)進(jìn)行解析注解炭晒,組裝Request
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
進(jìn)行 build 構(gòu)建RequestFactory
RequestFactory build() {
// 創(chuàng)建的 Service 接口方法中的參數(shù)注解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
}
return new RequestFactory(this);
}
在parseParameter()
就是根據(jù)Service
接口內(nèi)方法參數(shù),使用parseParameterAnnotation()
進(jìn)行遍歷對(duì)每個(gè)注解進(jìn)行解析
/** 解析具體的參數(shù)注解 */
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Content) {
validateResolvableType(p, type);
Converter<?, String> converter =
mRetrofit.stringConverter(type, annotations);
return new ParameterHandler.Content<>(converter);
}
return null;
}
@Content
是一個(gè)自己定義的注解
/** 內(nèi)容注解 */
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Content {
}
ParameterHandler
一個(gè)抽象類甥角,根據(jù)注解网严,實(shí)現(xiàn)了一個(gè)Content
子類,負(fù)責(zé)對(duì)注解進(jìn)行解析拼接嗤无。注解是RUNTIME
型的震束,為了加快讀取,使用ParameterHandler
static final class Content<T> extends ParameterHandler<T> {
private final Converter<T, String> mValueConverter;
Content(Converter<T, String> valueConverter) {
this.mValueConverter = valueConverter;
}
@Override
void apply(StringBuilder builder, T value) throws IOException {
builder.append(mValueConverter.convert(value));
}
}
在apply()
將注解標(biāo)記的參數(shù)拼接到StirngBuilder
当犯,在OkHttpCall
內(nèi)發(fā)起網(wǎng)路請(qǐng)求時(shí)驴一,會(huì)通過(guò)這個(gè)StirngBuilder
拿到Request Body
2.3.2 Response Body 轉(zhuǎn)換
在Retrofit.Builder
的build()
方法內(nèi),添加了一個(gè)BuiltInConverters
內(nèi)置的轉(zhuǎn)換器
converterFactories.add(new BuiltInConverters());
BuiltInConverters 內(nèi)置轉(zhuǎn)換器
/** 內(nèi)置的轉(zhuǎn)換器 */
final class BuiltInConverters extends Converter.Factory {
@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
// 由于簡(jiǎn)化過(guò)程沒(méi)有進(jìn)行 http 請(qǐng)求灶壶,最終都轉(zhuǎn)換成了 String
if (type == String.class) {
return ResponseBodyToStringConverter.INSTANCE;
}
// 返回 Void
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
/** Response Body 轉(zhuǎn)換成 String */
static final class ResponseBodyToStringConverter implements Converter<ResponseBody, String> {
static final ResponseBodyToStringConverter INSTANCE = new ResponseBodyToStringConverter();
@Override
public String convert(ResponseBody value) throws IOException {
return value.body();
}
}
}
在ResponseBodyToStringConverter
內(nèi)直接返回了ResponseBody.body()
肝断,也就是Stirng
本身
2.4 OkHttpCall
當(dāng)call.execute()
時(shí),最終會(huì)調(diào)用OkHttpCall
內(nèi)部邏輯驰凛,發(fā)起網(wǎng)絡(luò)請(qǐng)求
@Override
public Response<T> execute() throws IOException {
RawCall call;
synchronized (this) {
if (mExecuted) {
throw new IllegalStateException("Already executed.");
}
mExecuted = true;
call = mRawCall;
if (call == null) {
try {
call = mRawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throw e;
}
}
}
return parseResponse(call.execute());
}
在方法內(nèi)胸懈,會(huì)先創(chuàng)建RawCall
private RawCall createRawCall() throws IOException {
return new RawCall(mRequestFactory.create(mArgs));
}
在mRequestFactory.create()
內(nèi),會(huì)將ParameterHandler
存的解析的注解拼裝的Request Body
轉(zhuǎn)成String
parseResponse()
解析結(jié)果
private Response<T> parseResponse(String s) throws IOException {
T body = mResponseConverter.convert(new ResponseBody(s));
return Response.success(body);
}
根據(jù)創(chuàng)建的Response Body Converter
來(lái)解析恰响,之后構(gòu)建一個(gè)Response
類包裝下趣钱,返回
3. 最后
整個(gè)精簡(jiǎn)后的Demo
流程就這些,可以看看具體的代碼