雖然一個人
我并不孤獨
在心中你陪我看每一個日出
不要總是那么不甘寂寞,因為一個人的你可以讓自己心存很多念想,這些念想也必將成為你奮斗的目標(biāo)與動力。(開篇推歌一首,猛戳《陪我看日出》_)
項目——SimpleRetrofit地址:https://github.com/ms-liu/SimpleRetrofit/tree/master
序言
Retrofit
['retro?f?t]
v. 樣式翻新;改進(jìn)
n. 翻新;改進(jìn)
為什么先將Retrofit的英文單詞解釋放在最前面?
答:很簡單就是想提高一下大家英語水平([斜眼笑])。
為什么先將Retrofit單詞解釋放在最前面,其實大家都知道編碼當(dāng)中有一個難點就是起名字,因為好的名字總是很容易知道類的功能、方法的作用。所以個人覺得在帶著大家剖析Retrofit之前,有必要先讓大家知道Retrofit單詞的意思。因為這一個單詞還是能夠很好的說明Retrofit功能,可以說是它的核心思想吧。
話不多少,下面我們正式開始,因為文章篇幅較長,所以建議在電腦上,如果可以的話,可以打開Retrofit源碼或者SimpleRetrofit源碼。
一、如何使用?
我相信來看這篇文章的人,肯定是已經(jīng)使用過Retrofit,并且樂于學(xué)習(xí)的優(yōu)秀“程序猿”。這里只是想重新勾起你們的使用印象,希望耐心的看一下,防止下面剖析的時候會讓自己處于懵的狀態(tài)。
Demo:
//new出構(gòu)建Retrofit的Builder器
Retrofit.Builder builder = new Retrofit.Builder();
//添加請求BaseURL、轉(zhuǎn)換工廠、請求適配工廠、 調(diào)用構(gòu)建方法,構(gòu)建出Retrofit對象
Retrofit retrofit = builder
.baseUrl(API_URL)
.addConverterFactory(new DefaultConverterFactory())
.addCallAdapterFactory(DefaultCallAdapterFactory.INSTANCE)
.build();
//Retrofit調(diào)用create對象,創(chuàng)建API接口對象
Weather weather = retrofit.create(Weather.class);
//調(diào)用API接口中的方法,獲取到Call對象
Call<String> call = weather.getWeather("%E5%98%89%E5%85%B4&", "json", "5slgyqGDENN7Sy7pw29IUvrZ");
//調(diào)用Call的請求方法,
call.enqueue(new Callback<String>() {
//得到相應(yīng)結(jié)果
@Override
public void onResponse(Call<String> call, Response<String> response) {
String body = response.body();
System.out.println("==============="+body);
}
//得到失敗結(jié)果
@Override
public void onFailure(Call<String> call, Throwable throwable) {
System.err.println("異常:"+throwable.toString());
}
});
二、剖析
1、掌握Retrofit類
先看下面這個圖,掌握大概流程,讓腦海中有這副圖的印象。

(一)Retrofit構(gòu)造器
進(jìn)入Retrofit類中,先去看他的構(gòu)造方法( 畢竟要去使用一個類,我們首要的是能拿到它的對象,所以先看它的構(gòu)造方法)。
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
不難發(fā)現(xiàn)的是他需要大量的構(gòu)造參數(shù),要new出這樣的對象,無疑是痛苦且不具條理的。所以Retrofit選擇不對外提供該構(gòu)造方法,那么他是如何創(chuàng)建對象的呢?答案就是選擇Builder模式,來一步步的傳入所需要的參數(shù),將整個構(gòu)建過程清晰化,條理化。
(二)Retrofit內(nèi)部類——Builder
其實Builder中,就是將Retrofit構(gòu)造方法中所需的構(gòu)造參數(shù),分門別類的添加進(jìn)去,并且對于部分參數(shù)可義進(jìn)行默認(rèn)實現(xiàn)或初始化添加。主要部分的如下:
- baseUrl(String baseUrl)——添加基礎(chǔ)URL
- client(OkHttpClient client)——添加OkHttpClient對象
- addConverterFactory()——添加生產(chǎn)Converter的工廠類
- addCallAdapterFactory()——添加生產(chǎn)CallAdapter的工廠類
簡單講一下這兩個工廠類:
- Converter.Factory
那么現(xiàn)在開始思考,一個請求我們需要處理哪些東西呢?對~沒錯!就是RequestBody 和 ResponseBody(_);所以在Converter.Factory中要做的就是創(chuàng)建這兩種對應(yīng)的需求轉(zhuǎn)換器Converter,而這個Factory就是在Converter這個接口中的內(nèi)部類。
所以Converter.Factory是生產(chǎn)RequestBodyConverter和ResponseBodyConverter的生產(chǎn)廠或者車間。記?。。。τ谶@個工廠了解到這里就足夠了。
/**
* ==============================================
* 類名:Converter(Interface)
* 裝換器接口
*
* 內(nèi)部包含了一個創(chuàng)建轉(zhuǎn)換器的抽象工廠類
*
* 通過調(diào)用不同“加工方法”創(chuàng)建出不同轉(zhuǎn)換器
*
* 泛型:
* F=>轉(zhuǎn)換前類型
* T=>轉(zhuǎn)換后類型
* ==============================================
*/
public interface Converter<F,T> {
/**
* 具體轉(zhuǎn)換方法
* @param f
* @return
* @throws IOException
*/
T convert(F f) throws IOException;
abstract class Factory{
//創(chuàng)建ResponseBody轉(zhuǎn)換器 ResponseBody -> ?
public Converter<ResponseBody,?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit){
return null;
}
//創(chuàng)建RequestBody轉(zhuǎn)換器 ? -> RequestBody
public Converter<?, RequestBody> requestBodyConverter(
Type type,Annotation[] parameterAnnotations,Retrofit retrofit){
return null;
}
//創(chuàng)建String轉(zhuǎn)換器 ? -> String
public Converter<?,String> stringConverter(Type iterableType, Annotation[] parameterAnnotations, Retrofit retrofit){
return null;
}
}
}
- CallAdapter.Factory
這個工廠是用來生產(chǎn)CallAdpter,CallAdapter是將一個Call適配給另外一個Call的適配器接口。這個Call就是用來真正調(diào)起和發(fā)送網(wǎng)絡(luò)請求,并接受請求回調(diào)的。所以我們可以按照特定的需求(如:回調(diào)處理什么的...)去自定義這個Call,并通過CallAdapter中adpte方法去適配。再通過CallAdapter.Factory去創(chuàng)建CallAdapter,從而滿足需求。
public interface CallAdapter<R,T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory{
public abstract CallAdapter<?,?> get(Type returnType,
Annotation[] annotations,
Retrofit retrofit);
}
}
所以,如果我們想要按需求的制定Call,并且能夠在Retrofit中起作用需要經(jīng)過:
1、自定義CustomCall
2、自定義CustomCallAdapter,通過adpte方法返回自定義CustomCall
3、自定義CustomCallAdapterFactory,通過get方法返回自定義CustomCallAdapter
(三)Retrofit類中核心方法create();
經(jīng)過上面我們只是建造了一個大的工廠(包含了兩個重要車間:ConverterFactory、CallAdapterFactory),并且生產(chǎn)了Retrofit。
那么我們生產(chǎn)的Retrofit,它又是怎樣將原材料(定義的API接口)轉(zhuǎn)換成產(chǎn)品(網(wǎng)絡(luò)請求結(jié)果)的呢?答案就是Retrofit類中的create()方法。
貼出代碼:
(如果你選擇去看源碼可能與這個略有不同,因為這是本人改編的代碼)
@SuppressWarnings("unchecked")//解決代理創(chuàng)建對象時,泛型未檢查統(tǒng)一問題
public <T> T create(final Class<T> apiService){
if (!apiService.isInterface())
throw new IllegalArgumentException("API的定義必須是接口形式");
if (apiService.getInterfaces().length > 0)
throw new IllegalArgumentException("API的定義不允許繼承");
LogUtils.log("5、Retrofit中提供create()方法,通過動態(tài)代理方式,創(chuàng)建API接口對象");
return (T) Proxy.newProxyInstance(
apiService.getClassLoader(),
new Class<?>[]{apiService},
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class)
return method.invoke(this,args);
//加載處理API接口方法
ServiceMethod<Object,Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//創(chuàng)建OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//通過對應(yīng)的CallAdapter適配自定義并期望返回的Call
return serviceMethod.mCallAdapter.adapt(okHttpCall);
}
});
}
在這個方法中通過加載ServiceMethod(什么玩意?不急,后面會詳細(xì)說明),進(jìn)行API接口中的各種注解和參數(shù)值的處理。并通過CallAdapter去適配OkHttpCall從而得到自己所期望的Call或者對象。
現(xiàn)在我們再來看這張圖,是不是已經(jīng)能夠很好的梳理邏輯了呢?如果還不可以,那就自己再去翻翻Retrofit這個類的源碼看看。

2、理解ServiceMethod類
因為原Retrofit中的ServiceMethod相對較復(fù)雜,講解可能會比較復(fù)雜且混亂,所以在這里將會主要通過本人自己抽取ServiceMethod來進(jìn)行講解(因為我們不再需要再去造這一副輪子了,所以掌握理解即可)。
在ServiceMethod類中,同樣的也是包含了一個內(nèi)部類Builder,用于構(gòu)建ServiceMethod,下面我們一起,來一步步揭開這個Builder面紗[斜眼笑]。
(一)ServiceMethod.Builder的構(gòu)造方法
在這個構(gòu)造里面我們主要獲取Retrofit對象和API接口方法上的注解。
Builder(Retrofit retrofit, Method method){
LogUtils.log("7、初次創(chuàng)建API接口方法處理中心(ServiceMethod)");
//Retrofit實例
this.mRetrofit = retrofit;
//API接口中定義的方法
this.mMethod = method;
//API接口中方法上定義的注解--->@GET
this.mMethodAnnotations = method.getAnnotations();
//API接口中方法中的參數(shù)化注解
this.mParameterTypes = method.getGenericParameterTypes();
//API接口中方法中的所有參數(shù)注解
this.mParameterAnnotationsArray = method.getParameterAnnotations();
}
(二)解析構(gòu)建方法build()
在該方法中,最主要的:
- 創(chuàng)建CallAdapter——createCallAdapter()
- 創(chuàng)建ResponseConverter——createResponseConverter()
- 解析方法注解,獲取請求類型,獲取相對URL——parserMethodAnnotation()
- 解析參數(shù)注解,并創(chuàng)建對應(yīng)ParameterHandler,放入ParameterHandler [ ] 數(shù)組中
- 返回ServiceMethod對象,傳入Builder本身對象引用
public ServiceMethod build(){
this.mCallAdapter = createCallAdapter();
LogUtils.log("10、獲取CallAdapter中適配好的響應(yīng)類型");
this.mResponseType = mCallAdapter.responseType();
if (mResponseType == okhttp3.Response.class || mResponseType == Response.class)
throw new IllegalStateException("方法返回類型錯誤,需要的是ResponseBody");
this.mResponseConverter = createResponseConverter();
for (Annotation annotation:
mMethodAnnotations) {
LogUtils.log("13、解析方法上注解");
parseMethodAnnotation(annotation);
}
if (mMethodType == null)
throw new IllegalStateException("接口方法中必須需要是哪一種請求類型:@GET,@POST...");
int parameterCount = mParameterAnnotationsArray.length;
LogUtils.log("16、根據(jù)API接口中方法,注解參數(shù)的數(shù)量,創(chuàng)建對應(yīng)長度的參數(shù)處理器數(shù)組");
//根據(jù)參數(shù)數(shù)量,創(chuàng)建對應(yīng)長度的參數(shù)處理器數(shù)組。
mParameterHandlers = new ParameterHandler<?>[parameterCount];
LogUtils.log("循環(huán)遍歷注解參數(shù)====START");
for (int i = 0; i < parameterCount; i++){
Type parameterType = mParameterTypes[i];
Annotation[] parameterAnnotations = mParameterAnnotationsArray[i];
mParameterHandlers[i] = parserParameter(i,parameterType,parameterAnnotations);
}
LogUtils.log("循環(huán)遍歷注解參數(shù)====END");
return new ServiceMethod<>(this);
}
對接口方法中參數(shù)的解析,其實就是循環(huán)遍歷所有參數(shù)注解,然后獲取注解類型,根據(jù)不同類型創(chuàng)建不同的ParameterHandler。這里就不帖解析方法了,我相信大家自己去看源碼,肯定都是能弄明白的。這里選擇帶大家一起看一下ParameterHandler這里類。
對于ParameterHandler這個類的作用,其實就是將一個個的請求參數(shù),添加到網(wǎng)絡(luò)請求當(dāng)中去。
public abstract class ParameterHandler<T> {
/**
* 實現(xiàn)方法參數(shù)添加的方法
*/
abstract void apply(RequestBuilder builder,T value) throws IOException;
/**
* 針對@Query這種參數(shù)注解的ParameterHandler
* @param <T>
*/
static final class Query<T> extends ParameterHandler<T>{
private final String mQueryName;
private final Converter<T, String> mValueConverter;
private final boolean mUrlEncode;
Query(String name, Converter<T,String> valueConverter, boolean urlEncode){
this.mQueryName = name;
this.mValueConverter = valueConverter;
this.mUrlEncode = urlEncode;
}
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (mValueConverter == null) return;
//添加請求參數(shù)
builder.addQueryParams(mQueryName,mValueConverter.convert(value),mUrlEncode);
}
}
}
(三)拿到ServiceMethod對象后,應(yīng)該干什么?
- toRequest(Object...args),將請求中的參數(shù),通過ParameterHandler,添加到請求Request中,并返回Request
- toResponse(ResponseBody rawResponseBody),將原始的OKHttp的響應(yīng)體,通過Converter轉(zhuǎn)換
public ServiceMethod(Builder<R, T> builder) {
this.mCallFactory = builder.mRetrofit.mCallFactory;
this.mCallAdapter = builder.mCallAdapter;
this.mResponseConverter = builder.mResponseConverter;
this.mBaseUrl = builder.mRetrofit.mBaseUrl;
this.mRelativeUrl = builder.mRelativeUrl;
this.mMethod = builder.mMethod;
this.mMethodType = builder.mMethodType;
this.mParameterHandlers = builder.mParameterHandlers;
}
public Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(mMethodType, mBaseUrl, mRelativeUrl);
@SuppressWarnings("unchecked")
ParameterHandler<Object>[] mParameterHandlers = (ParameterHandler<Object>[]) this.mParameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != mParameterHandlers.length){
throw new IllegalStateException(
"待處理參數(shù)數(shù)量("+argumentCount+")與參數(shù)處理器數(shù)量("+mParameterHandlers.length+")不對應(yīng)"
);
}
for (int i=0;i<argumentCount;i++){
mParameterHandlers[i].apply(requestBuilder,args[i]);
}
return requestBuilder.build();
}
public R toResponse(ResponseBody rawBody) throws IOException {
return mResponseConverter.convert(rawBody);
}
在這里我們再用一張圖來進(jìn)行說明一下ServiceMethod這個類,幫助大家去理解。

3、再來講講OkHttpCall
OkHttpCall其實Retrofit內(nèi)部封裝的類,在OkHttpCall中封裝了OkHttp中的Call(用于網(wǎng)絡(luò)請求的發(fā)送或執(zhí)行)對象。它是Retrofit網(wǎng)絡(luò)請求發(fā)送過程中的實際發(fā)送者和網(wǎng)絡(luò)請求結(jié)果回調(diào)的第一手接受者。當(dāng)然也理解為OkHttpCall是Call(OkHttp中的)代理類。
另外在OkHttpCall中,還做了請求是否發(fā)起,是否取消等狀態(tài)的判讀和監(jiān)聽。當(dāng)然在當(dāng)前這個抽取的案例中沒有體現(xiàn),可以去實際源碼中查看??疵靼滓彩遣浑y的。
public class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> mServiceMethod;
private final Object[] mArgs;
private okhttp3.Call mRawCall;
OkHttpCall(ServiceMethod<T,?> serviceMethod, Object [] args){
LogUtils.log("17、創(chuàng)建OkHttpCall對象");
this.mServiceMethod = serviceMethod;
this.mArgs = args;
}
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call = null;
synchronized (this){
call = mRawCall;
if (call == null){
call = mRawCall = createRawCall();
}
}
LogUtils.log("18、調(diào)用execute,內(nèi)部調(diào)用OkHTTP3.Call的execute()");
return parserResponse(call.execute());
}
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call = null;
synchronized (this){
call = mRawCall;
if (call == null){
try {
call = mRawCall = createRawCall();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (call == null){
callback.onFailure(OkHttpCall.this,new Throwable("不能成功創(chuàng)建請求對象:call == null"));
return;
}
LogUtils.log("18、調(diào)用enqueue(帶有請求回調(diào)監(jiān)聽),內(nèi)部調(diào)用OkHTTP3.Call的enqueue()");
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callback.onFailure(OkHttpCall.this,e);
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
try {
//給一點點延時感
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Response<T> tResponse = parserResponse(response);
callback.onResponse(OkHttpCall.this,tResponse);
}
});
}
@Override
public synchronized Request request()throws IOException {
okhttp3.Call call = mRawCall;
if (call != null){
return call.request();
}
return (mRawCall = createRawCall()).request();
}
private Response<T> parserResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
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);
}
LogUtils.log("19、調(diào)用ServiceMethod.toResponse(),將OkHttp.ResponseBody轉(zhuǎn)換成期望的對象類");
T body = mServiceMethod.toResponse(rawBody);
return Response.success(body, rawResponse);
}
private okhttp3.Call createRawCall() throws IOException {
Request request = mServiceMethod.toRequest(mArgs);
okhttp3.Call call = mServiceMethod.mCallFactory.newCall(request);
if (call == null)
throw new NullPointerException("不能創(chuàng)建請求對象");
return call;
}
}
為了梳理與整理邏輯,現(xiàn)在我們再來一起看一下,一次簡單的Retrofit網(wǎng)絡(luò)請求中的日志輸出情況:
System.err: ============>0、創(chuàng)建Retrofit中Builder對象
System.err: ============>1、添加BaseUrl
System.err: ============>2、添加格式轉(zhuǎn)換工廠
System.err: ============>3、添加適配工廠
System.err: ============>4、構(gòu)建Retrofit對象
System.err: ============>5、Retrofit中提供create()方法,通過動態(tài)代理方式,創(chuàng)建API接口對象
System.err: ============>6、加載API接口方法處理中心(ServiceMethod),并緩存(優(yōu)先加載緩存中)
System.err: ============>初次做當(dāng)前API請,創(chuàng)建并緩存
System.err: ============>7、初次創(chuàng)建API接口方法處理中心(ServiceMethod)
System.err: ============>8、在ServiceMethod中創(chuàng)建適配器
System.err: ============>9、通過構(gòu)建Retrofit添加進(jìn)來的CallAdapterFactory創(chuàng)建CallAdapter
System.err: ============>10、獲取CallAdapter,適配好的響應(yīng)類型
System.err: ============>11、創(chuàng)建請求響應(yīng)轉(zhuǎn)換器
System.err: ============>12、通過構(gòu)建Retrofit添加進(jìn)來的ConverterFactory,創(chuàng)建請求響應(yīng)轉(zhuǎn)換器
System.err: ============>13、解析方法上注解
System.err: ============>14、判斷注解,獲取請求類型
System.err: ============>15、獲取相對的URL路徑
System.err: ============>16、根據(jù)API接口中方法,注解參數(shù)的數(shù)量,創(chuàng)建對應(yīng)長度的參數(shù)處理器數(shù)組
System.err: ============>循環(huán)遍歷注解參數(shù)====START
System.err: ============>>>>>>>根據(jù)API接口中方法的每一個注解參數(shù),創(chuàng)建對應(yīng)的參數(shù)處理器
System.err: ============>>>>>>>判斷參數(shù)注解類型是Query,創(chuàng)建對應(yīng)Query參數(shù)處理器
System.err: ============>>>>>>>根據(jù)API接口中方法的每一個注解參數(shù),創(chuàng)建對應(yīng)的參數(shù)處理器
System.err: ============>>>>>>>判斷參數(shù)注解類型是Query,創(chuàng)建對應(yīng)Query參數(shù)處理器
System.err: ============>>>>>>>根據(jù)API接口中方法的每一個注解參數(shù),創(chuàng)建對應(yīng)的參數(shù)處理器
System.err: ============>>>>>>>判斷參數(shù)注解類型是Query,創(chuàng)建對應(yīng)Query參數(shù)處理器
System.err: ============>循環(huán)遍歷注解參數(shù)====END
System.err: ============>17、創(chuàng)建OkHttpCall對象
System.err: ============>18、調(diào)用enqueue(帶有請求回調(diào)監(jiān)聽),內(nèi)部調(diào)用OkHTTP3.Call的enqueue()
System.err: ============>19、調(diào)用ServiceMethod.toResponse(),將OkHttp.ResponseBody轉(zhuǎn)換成期望的對象類
System.out: ===============>結(jié)果:{"status":201,"message":"APP被用戶自己禁用,請在控制臺解禁"}
三、回顧與總結(jié)
現(xiàn)在不知道有沒有理解Retrofit(翻修,改進(jìn))這個單詞的意思了呢。其實Retrofit(項目)就一個大的工廠,里面包含了多個工作車間,進(jìn)行著不同的分工合作。在ConverterFactory中創(chuàng)建著Converter(轉(zhuǎn)換器),在CallAdapterFactory中創(chuàng)建著CallAdapter(Call適配器),在ServiceMethod中調(diào)度著API接口中的各種注解并生組裝出對應(yīng)的ParameterHandler,在ParameterHandler中將各種參數(shù)值添加到Request(請求)當(dāng)中去,最后我們通過OkHttpCall調(diào)用真正的OkHttp中的Call進(jìn)行網(wǎng)絡(luò)請求,并且處理部分部分邏輯,返回結(jié)果。
所以Retrofit真的只是在翻修和改進(jìn)OkHttp,只需要將原材料(API接口),投入進(jìn)來,就可以生產(chǎn)出想要的產(chǎn)品(請求結(jié)果)。
至此,我們整個Retrofit主要東西已經(jīng)講完了?,F(xiàn)在如果你還處于懵的狀態(tài),那我相信你有可能是沒有認(rèn)真看完文章的內(nèi)容(這是對本人寫文章的“蜜汁”自信,我覺得最大原因應(yīng)該是本人真的沒有寫好吧)。如果是處于一知半解但是有那么一點思路的話,不著急,如果你愿意的話,你可以選擇繼續(xù)閱讀一遍文章。不過更加建議你的是帶著這么一點點思路自己去看看一遍Retrofit源碼,或者看SimpleRetrofit源碼。如果有不懂的話,可以選擇再來看看文章里面有沒有講到,或者選擇評論區(qū)里留言討論。
其實,從“站在樹蔭下的后人”的角度來說Retrofit,其實真的不難,因為他的代碼真的不多,設(shè)計模式也不復(fù)雜(工廠和Builder)。但其實如果是作為開發(fā)者和設(shè)計者,其實真的挺難的。因為Retrofit的擴(kuò)展性和易用性真的蠻高的,以及一些問題代碼的處理思想,如果不經(jīng)過磨練也確實是很難想到和做到的。所以“騷年”革命尚未成功,同志仍需努力。
結(jié)尾PS:
其實這篇文章寫的很糾結(jié),統(tǒng)共寫了三遍,有種想要放棄的念頭。因為感覺有些東西特別難闡述清楚,有些地方就是自己能夠清楚知道是有什么作用。但是很難組成書面詞表達(dá)出來(請對我這樣的一個“文科生”,投以關(guān)懷)。另外,雖然這篇已經(jīng)寫得很長了,但其實Retrofit中還有不少東西我都是沒有表達(dá)出來的,沒有寫全的,感覺還是蠻遺憾的?! ?br>
所以,好幾次都想直接錄一個視頻放出來。因為在視頻中可以更好的表達(dá)一些東西出來,那些很難表達(dá)出來的,直接可以通過“這個傻X東西”,“這玩意”、、、等一些詞直接帶過去,并且大家也不會歧義,感覺氣氛也會好一些_。
另外如果你能夠看到這個地方,如果覺得本人解析源碼的思路還可以的話,就請給出你想了解的框架或者項目的源碼。在評論區(qū)里面留言告知。本人嘗試看看能不能解析一下。多看別人代碼,永遠(yuǎn)比自己悶頭想,進(jìn)步更大。