Retrofit源碼分析

前言

????????Retrofit是Square公司開(kāi)源的一個(gè)針對(duì)OkHttp網(wǎng)絡(luò)請(qǐng)求接口進(jìn)行二次封裝的框架镰官,其網(wǎng)絡(luò)請(qǐng)求的實(shí)質(zhì)工作仍是由OkHttp來(lái)完成纵竖,主要工作是將網(wǎng)絡(luò)請(qǐng)求通過(guò)一系列注解的形式進(jìn)行拆解,并在最終執(zhí)行網(wǎng)絡(luò)請(qǐng)求前来累,將注解解析生成OkHttp請(qǐng)求所需的Okhttp3.Call泉褐。通過(guò)分析Retrofit源碼规哪,來(lái)達(dá)到深入理解Retrofit的工作流程與原理蛤袒,以及學(xué)習(xí)一些值得借鑒的設(shè)計(jì)模式和啟發(fā)一些解決問(wèn)題的思路熄云。
????????對(duì)于源碼中各種參數(shù)類型的相關(guān)知識(shí),如有不理解的地方妙真,可以參考賈博巖的兩篇文章:我眼中的Java-Type體系缴允。
http://www.reibang.com/p/7649f86614d3
http://www.reibang.com/p/e8eeff12c306

基本使用

第一步:集成

implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'

第二步:創(chuàng)建接口

public interface JianShuApi {

    @GET("user/{userName}/info")
    Observable<ResponseBody> getPersonalInfo(@Path("userName") String userName);

}

第三步:配置Retrofit并實(shí)例化

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.reibang.com")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build();

第四步:獲取接口對(duì)象

JianShuApi api = retrofit.create(JianShuApi.class);

第五步:執(zhí)行請(qǐng)求

Call<ResponseBody> call = api.getPersonalInfo("zhangSanLisi");
//異步請(qǐng)求
call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //成功回調(diào)
        }

       @Override
       public void onFailure(Call<ResponseBody> call, Throwable t) {
        //失敗回調(diào)
       }
});

//同步請(qǐng)求
try {
      Response<ResponseBody> response = call.execute();
} catch (IOException e) {
      e.printStackTrace();
}

源碼分析

下面我們按照使用流程來(lái)分析:

1、自定義接口類

里面的請(qǐng)求方法珍德,主要通過(guò)注解的方式來(lái)實(shí)現(xiàn)各種參數(shù)的靈活配置练般。如常用的請(qǐng)求方式@POST @GET,添加請(qǐng)求參數(shù)的@Query @QueryMap菱阵,大文件下載@Streaming踢俄,多文件提交@Multipart,請(qǐng)求頭內(nèi)容@Header @Headers...晴及,具體注解使用請(qǐng)參考retrofit2.http里面的內(nèi)容,每個(gè)注解都有相關(guān)的注釋嫡锌。

2虑稼、Retrofit.Builder

通過(guò)Retrofit.Builder構(gòu)造者模式來(lái)實(shí)例化Retrofit對(duì)象,主要可配置的內(nèi)容如下:

public static final class Builder {
    // 具體使用平臺(tái)势木,Platform.get()方法來(lái)獲取蛛倦,這里只分析Android
    private final Platform platform;
    // 指定用來(lái)構(gòu)建Call實(shí)例的Call.Factory類
    private @Nullable okhttp3.Call.Factory callFactory;
    // 請(qǐng)求的baseUrl,注釋建議我們使用相對(duì)路徑的方式來(lái)配置
    // Base URL: http://example.com/api/
    // Endpoint: foo/bar/
    // Result: http://example.com/api/foo/bar/
    private HttpUrl baseUrl;
    // 用于對(duì)象序列化(serialization)和反序列化(deserialization)啦桌,常用GsonConverterFactory
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 請(qǐng)求返回類型(除了Call之外)溯壶,若Retrofit結(jié)合RxJava一起使用,那么就可以添加RxJava2CallAdapterFactory
    // 來(lái)返回Observable類型甫男,無(wú)縫對(duì)接RxJava
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 異步回調(diào)執(zhí)行者
    private @Nullable Executor callbackExecutor;
    // 是否提前校驗(yàn)注解方法
    private boolean validateEagerly;

    ......

    public Retrofit build() {
        // 必須指定baseUrl且改,否則異常
        if (baseUrl == null) {
             throw new IllegalStateException("Base URL required.");
        }
        //默認(rèn)OkHttpClient來(lái)創(chuàng)建請(qǐng)求Call
        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
            callFactory = new OkHttpClient();
        }
        // Android平臺(tái)默認(rèn)回調(diào)在主線程
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
           callbackExecutor = platform.defaultCallbackExecutor();
        }
        // 默認(rèn)添加一個(gè)CallAdapter和Converter
        // Make a defensive copy of the adapters and add the default Call adapter.
        List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); 
        callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

        // Make a defensive copy of the converters.
        List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size());
        // 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);

        return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
                    unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
}
3、Retrofit.create()
public final class Retrofit {
......
public <T> T create(final Class<T> service) {
        // 校驗(yàn)class必須是接口板驳,并且不能繼承其他接口
        Utils.validateServiceInterface(service);
        // 是否提前校驗(yàn)方法又跛,提前創(chuàng)建ServiceMethod,如果自定義的接口方法存在不合規(guī)范則拋出異常
        if (validateEagerly) {
                eagerlyValidateMethods(service);
        }
        // 返回一個(gè)代理對(duì)象若治,當(dāng)調(diào)用api方法的時(shí)候慨蓝,代理對(duì)象執(zhí)行
        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, 
                                            @Nullable 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);
                         }
                         if (platform.isDefaultMethod(method)) {
                             return platform.invokeDefaultMethod(method, service, proxy, args);
                         }
                         // 下面這兩行是核心代碼感混,生成ServiceMethod和請(qǐng)求OkHttpCall
                         ServiceMethod<Object, Object> serviceMethod =
                                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                         OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                         // 執(zhí)行adapt方法,返回指定的數(shù)據(jù)類型礼烈,具體內(nèi)容會(huì)在后面CallAdapter類中說(shuō)明
                         return serviceMethod.adapt(okHttpCall);
                     }
                });
        }

......

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    // 同步鎖
    synchronized (serviceMethodCache) {
        //  通過(guò)method對(duì)象弧满,獲取對(duì)應(yīng)緩存的ServiceMethod
        result = serviceMethodCache.get(method);
        if (result == null) {
            // 創(chuàng)建ServiceMethod并存入緩存
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
        }
    }
    return result;
  }
......
}

到這里我們就拿到了接口代理對(duì)象對(duì)象,當(dāng)調(diào)用接口具體方法api.getPersonalInfo("zhangSanLisi");的時(shí)候就會(huì)執(zhí)行invoke方法此熬,獲取創(chuàng)建的ServiceMethod對(duì)象庭呜,執(zhí)行serviceMethod.adapt(okHttpCall)方法,這里我們指定了請(qǐng)求適配器為RxJava2CallAdapter摹迷,則返回Observable疟赊。具體參見(jiàn)下面RxJava2CallAdapter的adapt方法

4、ServiceMethod

這是Retrofit框架核心類峡碉。ServiceMethod類功能是將自定義的接口方法解析適配成Http調(diào)用的Call近哟,也就是生成Http請(qǐng)求。該類也是通過(guò)構(gòu)造者模式實(shí)例化:new ServiceMethod.Builder<>(this, method).build()鲫寄。

final class ServiceMethod<R, T> {
    ......
    // 這個(gè)方法會(huì)在創(chuàng)建真正OkHttp請(qǐng)求時(shí)調(diào)用吉执,即OkHttpCall類中createRawCall()方法
    // 參見(jiàn)下面OkHttpCall分析里enqueue方法
    okhttp3.Call toCall(@Nullable Object... args) throws IOException {
        // 通過(guò)構(gòu)造者模式RequestBuilder來(lái)創(chuàng)建請(qǐng)求Request
        // 里面有使用到ServiceMethod生成的ParameterHandler對(duì)象,主要是解析不同的請(qǐng)求參數(shù)地来,大家可自行查看源碼分析
        RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
                contentType, hasBody, isFormEncoded, isMultipart);

        @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
                ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

        int argumentCount = args != null ? args.length : 0;
        if (argumentCount != handlers.length) {
            throw new IllegalArgumentException("Argument count (" + argumentCount
                    + ") doesn't match expected count (" + handlers.length + ")");
        }

        for (int p = 0; p < argumentCount; p++) {
            handlers[p].apply(requestBuilder, args[p]);
        }
        // 最終回通過(guò)Retrofit里面指定的callFactory執(zhí)行戳玫,這里不指定時(shí),默認(rèn)是OkHttpClient未斑,這里不做進(jìn)一步分析咕宿,具體可參考OkHttp源碼。
        return callFactory.newCall(requestBuilder.build());
    }
    ......
    static final class Builder<T, R> {
        ......
        Builder(Retrofit retrofit, Method method) {
            this.retrofit = retrofit;
            this.method = method;
            // 獲取方法注解蜡秽, 如@POST府阀、@Headers
            this.methodAnnotations = method.getAnnotations();
            // 獲取方法參數(shù)類型,如String
            this.parameterTypes = method.getGenericParameterTypes();
            // 獲取方法參數(shù)注解芽突,如@Query
            this.parameterAnnotationsArray = method.getParameterAnnotations();
        }

        public ServiceMethod build () {
            /* 
            * 一系列判斷之后調(diào)用的是 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
            * 遍歷Retrofit配置時(shí)設(shè)置的callAdapterFactories试浙,如果設(shè)置的是RxJava2CallAdapterFactory最終調(diào)用其get方法;
            * 經(jīng)過(guò)一系列的返回類型判斷寞蚌,最終返回CallAdapter田巴,這里也就是RxJava2CallAdapter
            */
            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?");
            }
            /* 
            * 獲取轉(zhuǎn)換器,也就是序列化和反序列化方式挟秤,retrofit.responseBodyConverter(responseType, annotations);
            * 遍歷Retrofit配置時(shí)設(shè)置的converterFactories壹哺,設(shè)置的Gson,則會(huì)調(diào)用GsonConverterFactory的responseBodyConverter方法煞聪;
            * 返回GsonResponseBodyConverter類斗躏,這里將在后面響應(yīng)回調(diào)分析中使用到。
            */
            responseConverter = createResponseConverter();
            for (Annotation annotation : methodAnnotations) {
                // 遍歷方法注解,這里會(huì)解析自定義接口里的方法注解并獲取對(duì)應(yīng)的value啄糙,為最后創(chuàng)建請(qǐng)求okhttp3.Call準(zhǔn)備參數(shù)
                parseMethodAnnotation(annotation);
            }
            // 是否指定了請(qǐng)求方式
            if (httpMethod == null) {
                throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
            }
            // 校驗(yàn)請(qǐng)求方式與編碼方式是否不合理笛臣。FormUrlEncoded和Multipart這兩種編碼方式必須使用在有請(qǐng)求體的請(qǐng)求方式中,如:@POST隧饼,@PUT
            if (!hasBody) {
                if (isMultipart) {
                    throw methodError("Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
                }
                if (isFormEncoded) {
                    throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
                            + "request body (e.g., @POST).");
                }
            }
            // 下面是方法參數(shù)注解解析并獲取其對(duì)應(yīng)的value沈堡,方法參數(shù)類型不能是泛型和通配符
            int parameterCount = parameterAnnotationsArray.length;
            parameterHandlers = new ParameterHandler<?>[parameterCount];
            for (int p = 0; p < parameterCount; p++) {
                Type parameterType = parameterTypes[p];
                if (Utils.hasUnresolvableType(parameterType)) {
                    throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
                            parameterType);
                }
                Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
                if (parameterAnnotations == null) {
                    throw parameterError(p, "No Retrofit annotation found.");
                }
                // 這里parseParameter方法會(huì)調(diào)用到Retrofit中requestBodyConverter方法
                // 即GsonRequestBodyConverter類中的convert方法,進(jìn)行數(shù)據(jù)序列化燕雁。
                parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
            }
            // 下面一些是判斷方法參數(shù)注解與請(qǐng)求方式诞丽、編碼方式是否匹配或沖突
            if (relativeUrl == null && !gotUrl) {
                throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
            }
            if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
                throw methodError("Non-body HTTP method cannot contain @Body.");
            }
            if (isFormEncoded && !gotField) {
                throw methodError("Form-encoded method must contain at least one @Field.");
            }
            if (isMultipart && !gotPart) {
                throw methodError("Multipart method must contain at least one @Part.");
            }
            // 最終返回ServiceMethod實(shí)例對(duì)象
            return new ServiceMethod<>(this);
        }
    }
......
}

GsonRequestBodyConverter

final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }

    @Override public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}
5、RxJava2CallAdapter

這里根據(jù)設(shè)置生成相對(duì)應(yīng)的RxJava的被觀察者對(duì)象

final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
......
    @Override public Object adapt(Call<R> call) {
        // 這里我們只考慮異步的情況拐格,同步基本一致僧免。生成CallEnqueueObservable對(duì)象,call為OkHttpCall
        Observable<Response<R>> responseObservable = isAsync
                        ? new CallEnqueueObservable<>(call)
                        : new CallExecuteObservable<>(call);

        Observable<?> observable;
        if (isResult) {
            observable = new ResultObservable<>(responseObservable);
        } else if (isBody) {
            observable = new BodyObservable<>(responseObservable);
        } else {
            observable = responseObservable;
        }
        // 指定運(yùn)行線程捏浊,RxJava2CallAdapterFactory.createWithScheduler(Scheduler)指定創(chuàng)建
        if (scheduler != null) {
            observable = observable.subscribeOn(scheduler);
        }
        if (isFlowable) {
            return observable.toFlowable(BackpressureStrategy.LATEST);
        }
        if (isSingle) {
            return observable.singleOrError();
        }
        if (isMaybe) {
            return observable.singleElement();
        }
        if (isCompletable) {
            return observable.ignoreElements();
        }
        return observable;
    }
}
6懂衩、CallEnqueueObservable

RxJava的方法調(diào)用,當(dāng)被觀察者調(diào)用.subscribe()訂閱之后金踪,會(huì)調(diào)用到里面的subscribeActual()方法浊洞。

final class CallEnqueueObservable<T> extends Observable<Response<T>> {
        ......

        @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
            // Since Call is a one-shot type, clone it for each new observer.
            Call<T> call = originalCall.clone();
            retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<T> callback = new retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<>(call, observer);
            observer.onSubscribe(callback);
            // 這里是將call加入隊(duì)列,并傳入下面的CallCallback對(duì)象胡岔,異步請(qǐng)求法希。前面我們說(shuō)過(guò)這歌call對(duì)象是OkHttpCall。
            call.enqueue(callback);
        }

        private static final class CallCallback<T> implements Disposable, Callback<T> {
        ......
            //下面是正確和失敗回調(diào)靶瘸,即調(diào)用onNext和onError方法
            @Override public void onResponse(Call<T> call, Response<T> response) {
                if (disposed) return;
                try {
                    observer.onNext(response);
                    if (!disposed) {
                        terminated = true;
                        observer.onComplete();
                    }
                 } catch (Throwable t) {
                  ......          
                 }
             }

             @Override public void onFailure(Call<T> call, Throwable t) {
                 if (call.isCanceled()) return;
                 try {
                    observer.onError(t);
                 } catch (Throwable inner) {
                  ......      
                 }
              }
        }
}
7苫亦、OkHttpCall

上面call.enqueue(callback)實(shí)際走的就是OkHttpCall的enqueue方法。

final class OkHttpCall<T> implements Call<T> {
    ......
    @Override
    public void enqueue(final Callback<T> callback) {
        // 回調(diào)非空判斷
        checkNotNull(callback, "callback == null");
        okhttp3.Call call;
        Throwable failure;
        // 同步鎖怨咪,創(chuàng)建真正發(fā)起網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call著觉,會(huì)ServiceMethod類里toCall方法
        synchronized (this) {
            //  這里會(huì)對(duì)請(qǐng)求是否執(zhí)行過(guò)判斷,也就是說(shuō)代理對(duì)象方法里生成的OkHttpCall只能執(zhí)行一次
            if (executed) throw new IllegalStateException("Already executed.");
            executed = true;
            call = rawCall;
            failure = creationFailure;
            if (call == null && failure == null) {
                try {
                    call = rawCall = createRawCall();
                } catch (Throwable t) {
                    throwIfFatal(t);
                    failure = creationFailure = t;
                }
            }
        }

        if (failure != null) {
            callback.onFailure(this, failure);
            return;
        }

        if (canceled) {
            call.cancel();
        }
        // 這里就轉(zhuǎn)到了OkHttp網(wǎng)絡(luò)請(qǐng)求框架惊暴,加入到請(qǐng)求隊(duì)列里面。
        // 最后回調(diào)回調(diào)用CallEnqueueObservable中的CallCallback趁桃,即onNext或onError方法
        call.enqueue(new okhttp3.Callback() {
            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                Response<T> response;
                try {
                    // 這里是解析響應(yīng)數(shù)據(jù)方法
                    response = parseResponse(rawResponse);
                } catch (Throwable e) {
                    callFailure(e);
                    return;
                }

                try {
                    callback.onResponse(retrofit2.OkHttpCall.this, response);
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }

            @Override
            public void onFailure(okhttp3.Call call, IOException e) {
                callFailure(e);
            }

            private void callFailure(Throwable e) {
                try {
                    callback.onFailure(retrofit2.OkHttpCall.this, e);
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
        });
    }
    ......
    private okhttp3.Call createRawCall() throws IOException {
        // 調(diào)用的是ServiceMethod里面的toCall()方法
        okhttp3.Call call = serviceMethod.toCall(args);
        if (call == null) {
            throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
    }
}

下面我們看下異步請(qǐng)求的回調(diào)辽话,這里只分析成功回調(diào),失敗回調(diào)是一樣的卫病。
在上面enqueue方法回調(diào)中有parseResponse(rawResponse)這么一行代碼油啤,它做的就是解析響應(yīng)數(shù)據(jù)的功能。

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();

        // Remove the body's source (the only stateful object) so we can pass the response along.
        rawResponse = rawResponse.newBuilder()
                .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
                .build();

        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);
        }

        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
            // 這里是核心代碼
            T body = serviceMethod.toResponse(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;
        }
    }

ServiceMethod類中toResponse方法:

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}

這里直接分析核心代碼T body = serviceMethod.toResponse(catchingBody);蟀苛,通過(guò)源碼可以看到益咬,最終其調(diào)用的是Retrofit配置時(shí)設(shè)置的converterFactories類的convert方法,返回設(shè)定的對(duì)象帜平,即反序列化響應(yīng)數(shù)據(jù)幽告。

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson gson;
    private final TypeAdapter<T> adapter;

    GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }

    @Override public T convert(ResponseBody value) throws IOException {
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
            T result = adapter.read(jsonReader);
            if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
                throw new JsonIOException("JSON document was not fully consumed.");
            }
            return result;
        } finally {
            value.close();
        }
    }
}
8梅鹦、ExecutorCallAdapterFactory

如果我們沒(méi)有添加CallAdapterFactory請(qǐng)求適配器,則會(huì)使用Android平臺(tái)默認(rèn)請(qǐng)求適配器ExecutorCallAdapterFactory冗锁,調(diào)用enqueue方法時(shí)會(huì)走ExecutorCallbackCall中的enqueue方法齐唆,然后執(zhí)行OkHttpCall的enqueue方法,代碼如下:

@Override public void enqueue(final Callback<T> callback) {
        checkNotNull(callback, "callback == null");
        // 這里的delegate就是OkHttpCall冻河,最終還是走到OkHttpCall的enqueue方法
        delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> response) {
                callbackExecutor.execute(new Runnable() {
                    @Override public void run() {
                        if (delegate.isCanceled()) {
                            // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                            callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, response);
                        }
                    }
                });
            }

            @Override public void onFailure(Call<T> call, final Throwable t) {
                callbackExecutor.execute(new Runnable() {
                    @Override public void run() {
                        callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, t);
                    }
                });
            }
        });
    }
9箍邮、BuiltInConverters

如果沒(méi)有添加ConverterFactory,則會(huì)使用默認(rèn)的BuiltInConverters進(jìn)行requestBody序列化和responseBody反序列化叨叙。當(dāng)然锭弊,在BuiltInConverters還存在一個(gè)重要的類ToStringConverter,不管有沒(méi)有額外添加ConverterFactory擂错,其在ServiceMethod進(jìn)行注解解析時(shí)都會(huì)使用到味滞,具體參見(jiàn)ServiceMethod類中的ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)方法。

final class BuiltInConverters extends Converter.Factory {
    // 響應(yīng)數(shù)據(jù)反序列化轉(zhuǎn)換器
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        // 根據(jù)要求響應(yīng)數(shù)據(jù)類型的不同马昙,返回不同的converter
        if (type == ResponseBody.class) {
            return Utils.isAnnotationPresent(annotations, Streaming.class)
                    ? retrofit2.BuiltInConverters.StreamingResponseBodyConverter.INSTANCE
                    : retrofit2.BuiltInConverters.BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) {
            return retrofit2.BuiltInConverters.VoidResponseBodyConverter.INSTANCE;
        }
        return null;
    }
    // 請(qǐng)求體數(shù)據(jù)序列化轉(zhuǎn)化器
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, 
                                Annotation[] methodAnnotations, Retrofit retrofit) {
        if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
            return retrofit2.BuiltInConverters.RequestBodyConverter.INSTANCE;
        }
        return null;
    }

    static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
        static final retrofit2.BuiltInConverters.VoidResponseBodyConverter 
                        INSTANCE = new retrofit2.BuiltInConverters.VoidResponseBodyConverter();
        @Override public Void convert(ResponseBody value) {
            // 不需要返回桃犬,直接close,返回null
            value.close();
            return null;
        }
    }
    // RequestBody請(qǐng)求體轉(zhuǎn)換器
    static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
        static final retrofit2.BuiltInConverters.RequestBodyConverter 
                  INSTANCE = new retrofit2.BuiltInConverters.RequestBodyConverter();
        @Override public RequestBody convert(RequestBody value) {
            return value;
        }
    }
    // 流轉(zhuǎn)換器
    static final class StreamingResponseBodyConverter
            implements Converter<ResponseBody, ResponseBody> {
        static final retrofit2.BuiltInConverters.StreamingResponseBodyConverter 
                  INSTANCE = new retrofit2.BuiltInConverters.StreamingResponseBodyConverter();
        @Override public ResponseBody convert(ResponseBody value) {
            return value;
        }
    }
    // 容器轉(zhuǎn)換器
    static final class BufferingResponseBodyConverter
            implements Converter<ResponseBody, ResponseBody> {
        static final retrofit2.BuiltInConverters.BufferingResponseBodyConverter
                    INSTANCE = new retrofit2.BuiltInConverters.BufferingResponseBodyConverter();
        @Override public ResponseBody convert(ResponseBody value) throws IOException {
            try {
                // Buffer the entire body to avoid future I/O.
                return Utils.buffer(value);
            } finally {
                value.close();
            }
        }
    }
    // 轉(zhuǎn)換成String
    static final class ToStringConverter implements Converter<Object, String> {
        static final retrofit2.BuiltInConverters.ToStringConverter 
                     INSTANCE = new retrofit2.BuiltInConverters.ToStringConverter();
        @Override public String convert(Object value) {
            return value.toString();
        }
    }
}

注意事項(xiàng)

通過(guò)源碼的分析行楞,發(fā)現(xiàn)一些特別需要注意的事項(xiàng):
1攒暇、必須指定一個(gè)請(qǐng)求方式,并且不能設(shè)置兩個(gè)或兩個(gè)以上子房,請(qǐng)求方式有:@POST形用、@GET、@DELETE证杭、@HEAD田度、@PATCH、@PUT解愤、@OPTIONS镇饺、@HTTP;
2送讲、Retrofit配置時(shí)設(shè)置的baseUrl與設(shè)置請(qǐng)求方式對(duì)應(yīng)的relativeUrl奸笤,結(jié)合后要是一個(gè)合理的url,不能同時(shí)relativeUrl為null哼鬓,而又不添加@Url监右;
3、返回?cái)?shù)據(jù)類型不能是Retrofit中的Responseokhttp3.Response异希;
4健盒、請(qǐng)求過(guò)程中生成OkHttpCall對(duì)象,只能調(diào)用一次請(qǐng)求,不能重復(fù)調(diào)用扣癣;
5惰帽、默認(rèn)響應(yīng)數(shù)據(jù)返回ResponseBody, 請(qǐng)求體@Body可使用RequestBody搏色,當(dāng)使用自定義實(shí)體bean時(shí)善茎,不管做為@Body值還是作為響應(yīng)數(shù)據(jù)類型都必須添加一個(gè)ConverterFactory,如常用的GsonConverterFactory频轿;
6垂涯、注解的使用不能胡亂搭配,比如:@Multipart和@isFormEncoded與@GET等沒(méi)有請(qǐng)求體的請(qǐng)求方式一起使用航邢,再者添加了@Multipart耕赘,在參數(shù)里面必須要有@Part注解。具體的可以分析ServiceMethod類中的parseParameterAnnotation方法膳殷。

總結(jié)

????????這次分析以Retrofit使用流程為主線操骡,熟悉Retrofit的工作機(jī)制以及一些注意事項(xiàng)。Retrofit中使用了幾種設(shè)計(jì)模式:構(gòu)造者模式(Builder)赚窃、工廠模式(Factory)册招、策略模式(不同的CallAdapter和Converter)、觀察者模式等等勒极,這些都是在以后的工作中可以值得借鑒的地方是掰。還有就是注解的使用,這是一個(gè)很好的范例辱匿,基本上注解使用和解析的相關(guān)知識(shí)全部都涉及到了键痛,可以閱讀一下文章開(kāi)始推薦的Java-Type體系,是兩篇值得一讀好文章匾七。
????????以上就是本次分析的全部?jī)?nèi)容絮短,由于個(gè)人能力有限,如有不足或錯(cuò)誤的地方昨忆,敬請(qǐng)諒解丁频。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市邑贴,隨后出現(xiàn)的幾起案子限府,更是在濱河造成了極大的恐慌,老刑警劉巖痢缎,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異世澜,居然都是意外死亡独旷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嵌洼,“玉大人案疲,你說(shuō)我怎么就攤上這事÷檠” “怎么了褐啡?”我有些...
    開(kāi)封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鳖昌。 經(jīng)常有香客問(wèn)我备畦,道長(zhǎng),這世上最難降的妖魔是什么许昨? 我笑而不...
    開(kāi)封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任懂盐,我火速辦了婚禮,結(jié)果婚禮上糕档,老公的妹妹穿的比我還像新娘莉恼。我一直安慰自己,他們只是感情好速那,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布俐银。 她就那樣靜靜地躺著,像睡著了一般端仰。 火紅的嫁衣襯著肌膚如雪捶惜。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天榆俺,我揣著相機(jī)與錄音售躁,去河邊找鬼。 笑死茴晋,一個(gè)胖子當(dāng)著我的面吹牛陪捷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诺擅,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼市袖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了烁涌?” 一聲冷哼從身側(cè)響起苍碟,我...
    開(kāi)封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撮执,沒(méi)想到半個(gè)月后微峰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抒钱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年蜓肆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颜凯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仗扬,死狀恐怖症概,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情早芭,我是刑警寧澤彼城,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站退个,受9級(jí)特大地震影響募壕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帜乞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一司抱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黎烈,春花似錦习柠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至烈炭,卻和暖如春溶锭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背符隙。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工趴捅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人霹疫。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓拱绑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親丽蝎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猎拨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 最近非常流行 Retrofit+RxJava+OkHttp 這一整套的網(wǎng)絡(luò)請(qǐng)求和異步操作的開(kāi)源框架,從 Jake ...
    慌不要慌閱讀 1,974評(píng)論 1 7
  • 我在半年前才開(kāi)始接觸 Retrofit屠阻,在那個(gè)時(shí)候這個(gè)框架已經(jīng)很火了红省。作為入門學(xué)習(xí),簡(jiǎn)單梳理了一下寫成一篇文章国觉。有...
    龐哈哈哈12138閱讀 138評(píng)論 0 1
  • 有腦圖麻诀、有簡(jiǎn)筆畫蚜枢。祝大家周末快樂(lè)8滋印!厂抽!
    黑白度閱讀 524評(píng)論 3 3
  • 【雅靜4.4日讀書分享】。 一丁眼、銷售人員如何通過(guò)傾聽(tīng)筷凤,讓客戶買單? 1.全神貫注地去傾聽(tīng)用腦去研究對(duì)方話語(yǔ)背后的動(dòng)...
    雅靜_閱讀 139評(píng)論 0 0
  • 9月13日 哈哈苞七,好種子澆水施肥啦藐守!我近期的目標(biāo)是每月收入成倍的增長(zhǎng),獲得健康的身體蹂风,以此取得的能量服務(wù)于眾生卢厂。 ...
    穎默閱讀 59評(píng)論 0 1