Retrofit源码分析

前言

        Retrofit是Square公司开源的一个针对OkHttp网络请求接口进行二次封装的框架,其网络请求的实质工作仍是由OkHttp来完成,主要工作是将网络请求通过一系列注解的形式进行拆解,并在最终执行网络请求前,将注解解析生成OkHttp请求所需的Okhttp3.Call。通过分析Retrofit源码,来达到深入理解Retrofit的工作流程与原理,以及学习一些值得借鉴的设计模式和启发一些解决问题的思路。
        对于源码中各种参数类型的相关知识,如有不理解的地方,可以参考贾博岩的两篇文章:我眼中的Java-Type体系。
https://www.jianshu.com/p/7649f86614d3
https://www.jianshu.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'

第二步:创建接口

public interface JianShuApi {

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

}

第三步:配置Retrofit并实例化

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

第四步:获取接口对象

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

第五步:执行请求

Call<ResponseBody> call = api.getPersonalInfo("zhangSanLisi");
//异步请求
call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //成功回调
        }

       @Override
       public void onFailure(Call<ResponseBody> call, Throwable t) {
        //失败回调
       }
});

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

源码分析

下面我们按照使用流程来分析:

1、自定义接口类

里面的请求方法,主要通过注解的方式来实现各种参数的灵活配置。如常用的请求方式@POST @GET,添加请求参数的@Query @QueryMap,大文件下载@Streaming,多文件提交@Multipart,请求头内容@Header @Headers...,具体注解使用请参考retrofit2.http里面的内容,每个注解都有相关的注释。

2、Retrofit.Builder

通过Retrofit.Builder构造者模式来实例化Retrofit对象,主要可配置的内容如下:

public static final class Builder {
    // 具体使用平台,Platform.get()方法来获取,这里只分析Android
    private final Platform platform;
    // 指定用来构建Call实例的Call.Factory类
    private @Nullable okhttp3.Call.Factory callFactory;
    // 请求的baseUrl,注释建议我们使用相对路径的方式来配置
    // Base URL: http://example.com/api/
    // Endpoint: foo/bar/
    // Result: http://example.com/api/foo/bar/
    private HttpUrl baseUrl;
    // 用于对象序列化(serialization)和反序列化(deserialization),常用GsonConverterFactory
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 请求返回类型(除了Call之外),若Retrofit结合RxJava一起使用,那么就可以添加RxJava2CallAdapterFactory
    // 来返回Observable类型,无缝对接RxJava
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 异步回调执行者
    private @Nullable Executor callbackExecutor;
    // 是否提前校验注解方法
    private boolean validateEagerly;

    ......

    public Retrofit build() {
        // 必须指定baseUrl,否则异常
        if (baseUrl == null) {
             throw new IllegalStateException("Base URL required.");
        }
        //默认OkHttpClient来创建请求Call
        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
            callFactory = new OkHttpClient();
        }
        // Android平台默认回调在主线程
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
           callbackExecutor = platform.defaultCallbackExecutor();
        }
        // 默认添加一个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) {
        // 校验class必须是接口,并且不能继承其他接口
        Utils.validateServiceInterface(service);
        // 是否提前校验方法,提前创建ServiceMethod,如果自定义的接口方法存在不合规范则抛出异常
        if (validateEagerly) {
                eagerlyValidateMethods(service);
        }
        // 返回一个代理对象,当调用api方法的时候,代理对象执行
        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和请求OkHttpCall
                         ServiceMethod<Object, Object> serviceMethod =
                                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                         OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                         // 执行adapt方法,返回指定的数据类型,具体内容会在后面CallAdapter类中说明
                         return serviceMethod.adapt(okHttpCall);
                     }
                });
        }

......

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    // 同步锁
    synchronized (serviceMethodCache) {
        //  通过method对象,获取对应缓存的ServiceMethod
        result = serviceMethodCache.get(method);
        if (result == null) {
            // 创建ServiceMethod并存入缓存
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
        }
    }
    return result;
  }
......
}

到这里我们就拿到了接口代理对象对象,当调用接口具体方法api.getPersonalInfo("zhangSanLisi");的时候就会执行invoke方法,获取创建的ServiceMethod对象,执行serviceMethod.adapt(okHttpCall)方法,这里我们指定了请求适配器为RxJava2CallAdapter,则返回Observable。具体参见下面RxJava2CallAdapter的adapt方法

4、ServiceMethod

这是Retrofit框架核心类。ServiceMethod类功能是将自定义的接口方法解析适配成Http调用的Call,也就是生成Http请求。该类也是通过构造者模式实例化:new ServiceMethod.Builder<>(this, method).build()。

final class ServiceMethod<R, T> {
    ......
    // 这个方法会在创建真正OkHttp请求时调用,即OkHttpCall类中createRawCall()方法
    // 参见下面OkHttpCall分析里enqueue方法
    okhttp3.Call toCall(@Nullable Object... args) throws IOException {
        // 通过构造者模式RequestBuilder来创建请求Request
        // 里面有使用到ServiceMethod生成的ParameterHandler对象,主要是解析不同的请求参数,大家可自行查看源码分析
        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]);
        }
        // 最终回通过Retrofit里面指定的callFactory执行,这里不指定时,默认是OkHttpClient,这里不做进一步分析,具体可参考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();
            // 获取方法参数类型,如String
            this.parameterTypes = method.getGenericParameterTypes();
            // 获取方法参数注解,如@Query
            this.parameterAnnotationsArray = method.getParameterAnnotations();
        }

        public ServiceMethod build () {
            /* 
            * 一系列判断之后调用的是 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
            * 遍历Retrofit配置时设置的callAdapterFactories,如果设置的是RxJava2CallAdapterFactory最终调用其get方法;
            * 经过一系列的返回类型判断,最终返回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?");
            }
            /* 
            * 获取转换器,也就是序列化和反序列化方式,retrofit.responseBodyConverter(responseType, annotations);
            * 遍历Retrofit配置时设置的converterFactories,设置的Gson,则会调用GsonConverterFactory的responseBodyConverter方法;
            * 返回GsonResponseBodyConverter类,这里将在后面响应回调分析中使用到。
            */
            responseConverter = createResponseConverter();
            for (Annotation annotation : methodAnnotations) {
                // 遍历方法注解,这里会解析自定义接口里的方法注解并获取对应的value,为最后创建请求okhttp3.Call准备参数
                parseMethodAnnotation(annotation);
            }
            // 是否指定了请求方式
            if (httpMethod == null) {
                throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
            }
            // 校验请求方式与编码方式是否不合理。FormUrlEncoded和Multipart这两种编码方式必须使用在有请求体的请求方式中,如:@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).");
                }
            }
            // 下面是方法参数注解解析并获取其对应的value,方法参数类型不能是泛型和通配符
            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方法会调用到Retrofit中requestBodyConverter方法
                // 即GsonRequestBodyConverter类中的convert方法,进行数据序列化。
                parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
            }
            // 下面一些是判断方法参数注解与请求方式、编码方式是否匹配或冲突
            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实例对象
            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

这里根据设置生成相对应的RxJava的被观察者对象

final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
......
    @Override public Object adapt(Call<R> call) {
        // 这里我们只考虑异步的情况,同步基本一致。生成CallEnqueueObservable对象,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;
        }
        // 指定运行线程,RxJava2CallAdapterFactory.createWithScheduler(Scheduler)指定创建
        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的方法调用,当被观察者调用.subscribe()订阅之后,会调用到里面的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加入队列,并传入下面的CallCallback对象,异步请求。前面我们说过这歌call对象是OkHttpCall。
            call.enqueue(callback);
        }

        private static final class CallCallback<T> implements Disposable, Callback<T> {
        ......
            //下面是正确和失败回调,即调用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)实际走的就是OkHttpCall的enqueue方法。

final class OkHttpCall<T> implements Call<T> {
    ......
    @Override
    public void enqueue(final Callback<T> callback) {
        // 回调非空判断
        checkNotNull(callback, "callback == null");
        okhttp3.Call call;
        Throwable failure;
        // 同步锁,创建真正发起网络请求的okhttp3.Call,会ServiceMethod类里toCall方法
        synchronized (this) {
            //  这里会对请求是否执行过判断,也就是说代理对象方法里生成的OkHttpCall只能执行一次
            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();
        }
        // 这里就转到了OkHttp网络请求框架,加入到请求队列里面。
        // 最后回调回调用CallEnqueueObservable中的CallCallback,即onNext或onError方法
        call.enqueue(new okhttp3.Callback() {
            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                Response<T> response;
                try {
                    // 这里是解析响应数据方法
                    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 {
        // 调用的是ServiceMethod里面的toCall()方法
        okhttp3.Call call = serviceMethod.toCall(args);
        if (call == null) {
            throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
    }
}

下面我们看下异步请求的回调,这里只分析成功回调,失败回调是一样的。
在上面enqueue方法回调中有parseResponse(rawResponse)这么一行代码,它做的就是解析响应数据的功能。

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);,通过源码可以看到,最终其调用的是Retrofit配置时设置的converterFactories类的convert方法,返回设定的对象,即反序列化响应数据。

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

如果我们没有添加CallAdapterFactory请求适配器,则会使用Android平台默认请求适配器ExecutorCallAdapterFactory,调用enqueue方法时会走ExecutorCallbackCall中的enqueue方法,然后执行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

如果没有添加ConverterFactory,则会使用默认的BuiltInConverters进行requestBody序列化和responseBody反序列化。当然,在BuiltInConverters还存在一个重要的类ToStringConverter,不管有没有额外添加ConverterFactory,其在ServiceMethod进行注解解析时都会使用到,具体参见ServiceMethod类中的ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)方法。

final class BuiltInConverters extends Converter.Factory {
    // 响应数据反序列化转换器
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        // 根据要求响应数据类型的不同,返回不同的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;
    }
    // 请求体数据序列化转化器
    @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请求体转换器
    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;
        }
    }
    // 流转换器
    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;
        }
    }
    // 容器转换器
    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();
            }
        }
    }
    // 转换成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();
        }
    }
}

注意事项

通过源码的分析,发现一些特别需要注意的事项:
1、必须指定一个请求方式,并且不能设置两个或两个以上,请求方式有:@POST、@GET、@DELETE、@HEAD、@PATCH、@PUT、@OPTIONS、@HTTP;
2、Retrofit配置时设置的baseUrl与设置请求方式对应的relativeUrl,结合后要是一个合理的url,不能同时relativeUrl为null,而又不添加@Url;
3、返回数据类型不能是Retrofit中的Responseokhttp3.Response
4、请求过程中生成OkHttpCall对象,只能调用一次请求,不能重复调用;
5、默认响应数据返回ResponseBody, 请求体@Body可使用RequestBody,当使用自定义实体bean时,不管做为@Body值还是作为响应数据类型都必须添加一个ConverterFactory,如常用的GsonConverterFactory
6、注解的使用不能胡乱搭配,比如:@Multipart和@isFormEncoded与@GET等没有请求体的请求方式一起使用,再者添加了@Multipart,在参数里面必须要有@Part注解。具体的可以分析ServiceMethod类中的parseParameterAnnotation方法。

总结

        这次分析以Retrofit使用流程为主线,熟悉Retrofit的工作机制以及一些注意事项。Retrofit中使用了几种设计模式:构造者模式(Builder)、工厂模式(Factory)、策略模式(不同的CallAdapter和Converter)、观察者模式等等,这些都是在以后的工作中可以值得借鉴的地方。还有就是注解的使用,这是一个很好的范例,基本上注解使用和解析的相关知识全部都涉及到了,可以阅读一下文章开始推荐的Java-Type体系,是两篇值得一读好文章。
        以上就是本次分析的全部内容,由于个人能力有限,如有不足或错误的地方,敬请谅解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 最近非常流行 Retrofit+RxJava+OkHttp 这一整套的网络请求和异步操作的开源框架,从 Jake ...
    慌不要慌阅读 1,966评论 1 7
  • 我在半年前才开始接触 Retrofit,在那个时候这个框架已经很火了。作为入门学习,简单梳理了一下写成一篇文章。有...
    庞哈哈哈12138阅读 132评论 0 1
  • 有脑图、有简笔画。祝大家周末快乐!!!
    黑白度阅读 517评论 3 3
  • 【雅静4.4日读书分享】。 一、销售人员如何通过倾听,让客户买单? 1.全神贯注地去倾听用脑去研究对方话语背后的动...
    雅静_阅读 132评论 0 0
  • 9月13日 哈哈,好种子浇水施肥啦!我近期的目标是每月收入成倍的增长,获得健康的身体,以此取得的能量服务于众生。 ...
    颖默阅读 57评论 0 1