認(rèn)真看完這一篇,不懂Retrofit?不存在的(源碼解析)

雖然一個人
我并不孤獨
在心中你陪我看每一個日出

不要總是那么不甘寂寞,因為一個人的你可以讓自己心存很多念想,這些念想也必將成為你奮斗的目標(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)圖
(一)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)在開始思考,一個請求我們需要處理哪些東西呢?對~沒錯!就是RequestBodyResponseBody_);所以在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這個類的源碼看看。


Retrofit簡易流程架構(gòu)圖

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這個類,幫助大家去理解。

Retrofit中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)步更大。

實際代碼請下載或者Frok項目,若果能給start那就萬分感謝。

項目——SimpleRetrofit地址:https://github.com/ms-liu/SimpleRetrofit/tree/master

歡迎大家給出中肯的建議和提高意見,你的鼓勵將是我最大的動力。

個人郵箱:ms_liu163@163.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容