Retrofit2源码分析

Retrofit是一个Android网络框架,准确来说,Retrofit是一个 Restful风格的 HTTP 网络请求框架的封装,因为它的底层网络请求是通过OkHttp实现的,而它实际上是对网络请求接口层(请求方式、Header等信息)的封装。

Retrofit的简单使用

1、定义请求接口,配置网络请求参数

interface ApiService {

    @GET("v4/rankList")
    fun getCategories(): LiveData<HttpResult<CategoryDetailEntity>>
}

2、创建Retrofit实例

val retrofit = Retrofit.Builder()
            .baseUrl("http://baidu.com")
            .addCallAdapterFactory(LiveDataCallAdapterFactory())
            .addConverterFactory(GsonConverterFactory.create())
            .build()

通过Builder模式创建实例,可配置很多属性,例如CallAdapterConverterFactory

3、创建接口的动态代理对象

val apiService = retrofit.create(ApiService::class.java)

4、使用代理对象发起网络请求,并处理回调结果

apiService.getCategories().observe(this, Observer { httpResult ->

    if (true == httpResult?.isSuccessful) {
        println(httpResult.data)
    } else {
        Toast.makeText(this@MainActivity, httpResult?.msg, Toast.LENGTH_SHORT).show()
    }
})

源码分析

1、构建Retrofit实例

val retrofit = Retrofit.Builder()
            .baseUrl("http://baobab.kaiyanapp.com/api/")
            .addCallAdapterFactory(LiveDataCallAdapterFactory())
            .addConverterFactory(GsonConverterFactory.create())
            .build()

首先来看下Retrofit的属性:

// 用于缓存对网络请求接口注解进行解析后生成的对象
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

// 网络请求的工厂(对请求进行实际处理),默认使用okhttp
final okhttp3.Call.Factory callFactory;
// 网络请求基地址
final HttpUrl baseUrl;

// 数据转换器工厂集合,把响应数据转成特定的类型
final List<Converter.Factory> converterFactories;
// 网络请求适配器工厂集合,
final List<CallAdapter.Factory> callAdapterFactories;
// 回调方法执行器,切换线程
final @Nullable
Executor callbackExecutor;
// 标志位,用于标识是否提前对业务接口中的注解进行验证转换
final boolean validateEagerly;

Retrofit是使用建造者模式构建的,查看它的Builder类:

public static final class Builder {
        // Builder的属性和Retrofit的属性基本对应
        private final Platform platform;
        private @Nullable
        okhttp3.Call.Factory callFactory;
        private @Nullable
        HttpUrl baseUrl;
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
        private @Nullable
        Executor callbackExecutor;
        private boolean validateEagerly;

        Builder(Platform platform) {
            // 指定运行的平台
            this.platform = platform;
        }

        // 无参构造
        public Builder() {
            this(Platform.get()); // 调用有参构造
        }

        Builder(Retrofit retrofit) {
            platform = Platform.get();
            callFactory = retrofit.callFactory;
            baseUrl = retrofit.baseUrl;

            ...

            callbackExecutor = retrofit.callbackExecutor;
            validateEagerly = retrofit.validateEagerly;
        }

可以看到,Builder中的属性基本与Retrofit的相对应,而在构造方法中传入了Platform这个对象,这个对象指的是当前的运行平台是AndroidJava平台等,里面提供了默认回调执行器等,我们直接看下Android平台的关键代码:

class Platform {
    ...
    static class Android extends Platform {
            ...
            @Override
            public Executor defaultCallbackExecutor() {
                // 返回一个默认的回调方法执行器
                // 作用:切换线程,子->主线程,并再主线程中执行回调方法
                return new MainThreadExecutor();
            }
    
            @Override
            List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
                    @Nullable Executor callbackExecutor) {
                if (callbackExecutor == null) throw new AssertionError();
                // 默认请求适配器工厂
                DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
                return Build.VERSION.SDK_INT >= 24
                        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
                        : singletonList(executorFactory);
            }
    
            static class MainThreadExecutor implements Executor {
                // 获取主线程Handler
                private final Handler handler = new Handler(Looper.getMainLooper());
    
                @Override
                public void execute(Runnable r) {
                    handler.post(r); // 在主线程中处理网络请求返回的数据
                }
            }
        }
}

可以看出这个回调执行器的作用就是用于线程之间的切换,在ExecutorCallbackCall中的enqueue方法中调用了Call方法的enqueue方法,然后在回调中用MainThreadExecutor的execute方法通过handler切换到主线程处理。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    private final @Nullable
    Executor callbackExecutor;

    DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public @Nullable
    CallAdapter<?, ?> get(
            Type returnType, Annotation[] annotations, Retrofit retrofit) {
        ...
        final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

        final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
                ? null: callbackExecutor;

        return new CallAdapter<Object, Call<?>>() {
            @Override
            public Type responseType() {
                return responseType;
            }

            @Override
            public Call<Object> adapt(Call<Object> call) {
                return executor == null? call : new ExecutorCallbackCall<>(executor, call);
            }
        };
    }

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }

        @Override
        public void enqueue(final Callback<T> callback) {
            checkNotNull(callback, "callback == null");

            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(ExecutorCallbackCall.this, new IOException("Canceled"));
                            } else {
                                callback.onResponse(ExecutorCallbackCall.this, response);
                            }
                        }
                    });
                }

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

Builder类的baseUrl方法,作用是用来配置网络请求的基地址:

public Builder baseUrl(String baseUrl) {
    checkNotNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl));
}
    
public Builder baseUrl(HttpUrl baseUrl) {
    checkNotNull(baseUrl, "baseUrl == null");
    // 切割Url成路径碎片
    List<String> pathSegments = baseUrl.pathSegments();
    // 检测Url是否是以“/”结尾
    if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
    }
    this.baseUrl = baseUrl;
    return this;
}

检测Url是否是以“/”结尾,不是就抛出异常,将传入的String类型的url转成HttpUrl类型。

Builder类的addConverterFactory、addCallAdapterFactory方法:

public Builder addConverterFactory(Converter.Factory factory) {
    converterFactories.add(checkNotNull(factory, "factory == null"));
    return this;
}

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
    callAdapterFactories.add(checkNotNull(factory, "factory == null"));
    return this;
}

将数据转换工厂类和网络请求适配工厂类添加到对应的集合中,供后面使用。

Builder类的build方法:

public Retrofit build() {
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }

    // 配置网络请求执行器
    okhttp3.Call.Factory callFactory = this.callFactory;
    // 如果没指定,默认使用OkHttp
    if (callFactory == null) {
        callFactory = new OkHttpClient();
    }

    // 配置回调执行器
    Executor callbackExecutor = this.callbackExecutor;
    // 如果没指定,则使用平台的默认的callBackExecutor
    if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    // Make a defensive copy of the adapters and add the default Call adapter.
    // 配置网络适配器工厂集合
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    // Make a defensive copy of the converters.
    // 配置数据转换器工厂集合
    List<Converter.Factory> converterFactories = new ArrayList<>(
            1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

    // Add the built-in converter factory first. This prevents overriding its behavior but also
    // ensures correct behavior when using converters that consume all types.
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());

    // 构建Retrofit对象,传入上述已配置好的变量
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

将网络请求工厂、回调执行器、适配器集合等传入Retrofit的构造方法中,并返回Retrofit对象,到这里,Retrofit的属性都进行了初始化。

2、创建接口的动态代理对象

val apiService = retrofit.create(ApiService::class.java)

查看Retrofit的create方法:

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    // 判断是否需要提前验证
    if (validateEagerly) {
    	// 对接口中的每个方法的注解进行解析得到一个ServiceMethod的对象
        // 以Method为key存入一个Map集合中
        // 如果不提前验证,则会在调用方法时再对对应方法进行解析,最后将解析得到的ServiceMethod对象存入Map中
        eagerlyValidateMethods(service);
    }

    // 创建网络请求接口的动态代理对象
    return (T) Proxy.newProxyInstance(
            service.getClassLoader(), // 动态生成接口的实现类
            new Class<?>[]{service}, // 动态创建实例
            new InvocationHandler() { // 将代理类的实现交给InvocationHandler类作为具体实现
                private final Platform platform = Platform.get(); // 获取当前平台
                private final Object[] emptyArgs = new Object[0];

                @Override
                public @Nullable
                Object invoke(Object proxy, Method method,
                              @Nullable Object[] args) throws Throwable {
                    // If the method is a method from Object then defer to normal invocation.
                    // 如果方法定义所在的类是个Object,则直接调用对象方法
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }
                    if (platform.isDefaultMethod(method)) {
                        return platform.invokeDefaultMethod(method, service, proxy, args);
                    }

                    // 调用ServiceMethod方法的invoke唤醒方法
                    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                }
            });
}

通过代理模式生成一个代理对象用于访问目标对象,当使用代理对象调用方法时,调用都会集中到InvocationHandler的invoke方法上进行处理。

流程分析:

1、检验传进来的service是否是一个接口类型
2、判断是否需要提前验证,即提前去遍历解析接口方法,得到ServiceMethod对象并存入Map中,用于缓存获取
3、调用方法交由invoke方法内部处理
    3.1、判断如果当前方法所在的类是个Object,则直接通过invoke调用
    3.2、判断是否是default方法,如果是,则调用platform的invokeDefaultMethod处理
    3.3、调用loadServiceMethod(method)方法返回ServiceMethod对象后,再调用其invoke方法处理

接下来看下loadServiceMethod方法:

ServiceMethod<?> loadServiceMethod(Method method) {
    // 从Map缓存中取,如果有,则直接返回
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    // 单例模式获取ServiceMethod对象
    synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
            // 解析方法注解,返回ServiceMethod对象
            result = ServiceMethod.parseAnnotations(this, method);
            // 存入缓存Map中
            serviceMethodCache.put(method, result);
        }
    }
    return result;
}

判断当前方法是否已解析过(缓存中有没有),如果已解析,则直接返回,否则调用ServiceMethod的parseAnnotations对方法进行解析,再存入Map中。

查看ServiceMethod类:

abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        // 解析方法注解并返回RequestFactory对象
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

        Type returnType = method.getGenericReturnType();
        // 检测方法的返回值类型
        if (Utils.hasUnresolvableType(returnType)) {
            throw methodError(method,
                    "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
            throw methodError(method, "Service methods cannot return void.");
        }

        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }

    abstract @Nullable
    T invoke(Object[] args);
}

提供了两个方法,一个是parseAnnotations方法:用于解析方法注解,一个是invoke方法:用于调用对应的方法,进行网络请求。

parseAnnotations内部逻辑是:

1、对方法注解进行解析并返回一个RequestFactory对象(该对象内部封装了与请求的相关数据,例如,请求方式、请求参数等)
2、判断方法的返回类型是否合法
3、调用HttpServiceMethod的parseAnnotations并返回ServiceMethod对象

invoke方法由ServiceMethod子类实现,常见处理是传入参数等进行网络请求,再对返回值类型进行转化,再返回转化后的数据。

现在我们先看下RequestFactory是怎么从方法注解上解析出与请求相关的数据的:

final class RequestFactory {
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
    }

    private final Method method; // 当前方法
    private final HttpUrl baseUrl; // 基地址
    final String httpMethod; // 请求方式
    private final @Nullable
    String relativeUrl; // 参数部分的相对路径
    private final @Nullable
    Headers headers; // 请求头信息
    private final @Nullable
    MediaType contentType; // 请求报文body的类型
    private final boolean hasBody; // 是否有请求实体
    private final boolean isFormEncoded; // 是否表单数据
    private final boolean isMultipart; 
    private final ParameterHandler<?>[] parameterHandlers; // 方法参数处理器
    final boolean isKotlinSuspendFunction; // 是否使用了协程

可以看到RequestFactory也是通过建造者模式构建的,查看它的Builder类:

static final class Builder {
       ...
        final Retrofit retrofit;
        final Method method; // 方法
        final Annotation[] methodAnnotations; // 方法上的注解数组
        final Annotation[][] parameterAnnotationsArray; // 参数注解数组,二维数组(因为一个参数上可能也有多个注解)
        final Type[] parameterTypes; // 参数类型数组

        boolean gotField;
        boolean gotPart;
        boolean gotBody;
        boolean gotPath;
        boolean gotQuery;
        boolean gotQueryName;
        boolean gotQueryMap;
        boolean gotUrl;
       
        @Nullable
        String relativeUrl;
        @Nullable
        Headers headers;
        @Nullable
        MediaType contentType;
        @Nullable
        Set<String> relativeUrlParamNames;
        @Nullable
        ParameterHandler<?>[] parameterHandlers;
        boolean isKotlinSuspendFunction;

        Builder(Retrofit retrofit, Method method) {
            this.retrofit = retrofit;
            this.method = method;
            this.methodAnnotations = method.getAnnotations(); // 方法注解数组
            this.parameterTypes = method.getGenericParameterTypes(); // 参数类型数组
            this.parameterAnnotationsArray = method.getParameterAnnotations(); // 参数注解数组
        }

在参数上和RequestFactory属性基本对应,就是通过Builder类来对RequestFactory的属性进行初始化,查看build方法:

RequestFactory build() {
    // 遍历方法上的注解数组
    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);  // 解析方法上的注解
    }

    if (httpMethod == null) {
        // 没有配置请求方式的注解
        throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
    }

    // 判断使用注解方式是否正确
    if (!hasBody) {
        if (isMultipart) {
            throw methodError(method,
                    "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
            throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
                    + "request body (e.g., @POST).");
        }
    }

    // 参数注解个数
    int parameterCount = parameterAnnotationsArray.length;
    parameterHandlers = new ParameterHandler<?>[parameterCount];
    for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        // 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
        // 该对象的创建过程就是对方法参数中注解进行解析
        parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
    }

    if (relativeUrl == null && !gotUrl) {
        throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
    }
    if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError(method, "Non-body HTTP method cannot contain @Body.");
    }
    if (isFormEncoded && !gotField) {
        throw methodError(method, "Form-encoded method must contain at least one @Field.");
    }
    if (isMultipart && !gotPart) {
        throw methodError(method, "Multipart method must contain at least one @Part.");
    }

    return new RequestFactory(this);
}

流程分析:

1、遍历方法上的注解,调用parseMethodAnnotation方法解析注解
2、判断注解使用方式是否正确
3、对参数注解进行处理

查看parseMethodAnnotation方法:

 private void parseMethodAnnotation(Annotation annotation) {
    if (annotation instanceof DELETE) { // DELETE请求
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
    } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
    } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
    } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
    } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
    } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
    } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
    } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
    } else if (annotation instanceof retrofit2.http.Headers) { // 处理Header注解
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
            throw methodError(method, "@Headers annotation is empty.");
        }
        // 解析Header注解上的数据
        headers = parseHeaders(headersToParse);
    } else if (annotation instanceof Multipart) { // Multipart注解
        if (isFormEncoded) {
            throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isMultipart = true;
    } else if (annotation instanceof FormUrlEncoded) { // FormUrlEncoded注解
        if (isMultipart) {
            throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
    }
}

针对不同的请求方式处理,处理逻辑在parseHttpMethodAndPath方法内:

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
    // 检测是否已经解析过了
    if (this.httpMethod != null) {
        throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
                this.httpMethod, httpMethod);
    }
    this.httpMethod = httpMethod;
    this.hasBody = hasBody;

    if (value.isEmpty()) {
        return;
    }

    // Get the relative URL path and existing query string, if present.
    int question = value.indexOf('?'); // 获取请求链接中参数开始位置
    if (question != -1 && question < value.length() - 1) { // 有参数
        // Ensure the query string does not have any named parameters.
        String queryParams = value.substring(question + 1);
        Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
        if (queryParamMatcher.find()) {
            throw methodError(method, "URL query string \"%s\" must not have replace block. "
                    + "For dynamic query parameters use @Query.", queryParams);
        }
    }

    this.relativeUrl = value; // 参数部分的相对路径
    this.relativeUrlParamNames = parsePathParameters(value);
}

这里实际上就是对请求方式等属性进行赋值操作,然后判断请求链接中是否有参数,有则进行解析并给对应的属性赋值。

对参数进行处理的参数处理器ParameterHandler:

abstract class ParameterHandler<T> {

    // 子类实现注解解析,将注解的值value注入到builder中
    abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;

    // 迭代器解析,调用apply注入value值到builder中
    final ParameterHandler<Iterable<T>> iterable() {
        return new ParameterHandler<Iterable<T>>() {
            @Override
            void apply(RequestBuilder builder, @Nullable Iterable<T> values)
                    throws IOException {
                if (values == null) return; // Skip null values.

                for (T value : values) {
                    ParameterHandler.this.apply(builder, value);
                }
            }
        };
    }

    // 数组解析
    final ParameterHandler<Object> array() {
        return new ParameterHandler<Object>() {
            @Override
            void apply(RequestBuilder builder, @Nullable Object values) throws IOException {
                if (values == null) return; // Skip null values.

                for (int i = 0, size = Array.getLength(values); i < size; i++) {
                    //noinspection unchecked
                    ParameterHandler.this.apply(builder, (T) Array.get(values, i));
                }
            }
        };
    }

这个抽象类有很多子类对应@Header,@Path,@QueryMap等注解,作用就是将对应注解中的值,注入到RequestBuild中去。

到现在我们得到了RequestFactory对象,回到ServiceMethod的parseAnnotations中,接着调用了HttpServiceMethodparseAnnotations方法,并把retrofit、requestFactory、method作为参数传入:

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
            Retrofit retrofit, Method method, RequestFactory requestFactory) {
        boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
        boolean continuationWantsResponse = false;
        boolean continuationBodyNullable = false;

        Annotation[] annotations = method.getAnnotations(); // 获取方法上的注解数组
        Type adapterType;
        if (isKotlinSuspendFunction) { // 判断是否是使用了协程
            ...暂不分析
        }

        // 从Retrofit对象中获取到对应的网络请求适配器
        CallAdapter<ResponseT, ReturnT> callAdapter =
                createCallAdapter(retrofit, method, adapterType, annotations);
        Type responseType = callAdapter.responseType();
        // 判断返回类型是否正确
        if (responseType == okhttp3.Response.class) {
            throw methodError(method, "'"
                    + getRawType(responseType).getName()
                    + "' is not a valid response body type. Did you mean ResponseBody?");
        }
        if (responseType == Response.class) {
            throw methodError(method, "Response must include generic type (e.g., Response<String>)");
        }
        // TODO support Unit for Kotlin?
        if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
            throw methodError(method, "HEAD method must use Void as response type.");
        }

        // 从Retrofit对象中获取到对应的数据转换器
        Converter<ResponseBody, ResponseT> responseConverter =
                createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory; // 网络请求工厂,默认是OkHttp
        if (!isKotlinSuspendFunction) {
            // CallAdapted是HTTPServiceMethod的实现类
            return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
        } else if (continuationWantsResponse) {
            //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
            return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
                    callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
        } else {
            //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
            return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
                    callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
                    continuationBodyNullable);
        }
    }
    
    private final RequestFactory requestFactory;
    private final okhttp3.Call.Factory callFactory;
    private final Converter<ResponseBody, ResponseT> responseConverter;

整理流程:

1、根据方法注解和网络请求接口的返回值类型,从Retrofit对象中获取到对应的网络请求适配器,createCallAdapter方法
2、根据方法注解和网络请求接口的返回值类型,从Retrofit对象中获取到对应的数据转换器,createResponseConverter方法
3、获取请求工厂,默认是使用OkHttp
4、用上述几个获取的值作为参数构建出CallAdapter对象

获取网络请求适配器的createCallAdapter方法:

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
        Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
        //noinspection unchecked
        return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
}

调用了Retrofit的CallAdapter方法:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
}

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                         Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
        if (adapter != null) {
            return adapter;
        }
    }

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
            .append(returnType)
            .append(".\n");
    if (skipPast != null) {
        builder.append("  Skipped:");
        for (int i = 0; i < start; i++) {
            builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
        }
        builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
}

遍历CallAdapter工厂集合,查找返回值类型、方法注解相匹配的适配器对象,如果最终没有找到,则抛出异常。

获取数据转换器的createResponseConverter方法:

private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
        Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
        return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
}

调用了Retrofit的responseBodyConverter方法:
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
}

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
        @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
        Converter<ResponseBody, ?> converter =
                converterFactories.get(i).responseBodyConverter(type, annotations, this);
        if (converter != null) {
            //noinspection unchecked
            return (Converter<ResponseBody, T>) converter;
        }
    }

    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
            .append(type)
            .append(".\n");
    if (skipPast != null) {
        builder.append("  Skipped:");
        for (int i = 0; i < start; i++) {
            builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
        }
        builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
}

遍历数据转换器工厂集合,调用转换器类查找和返回值、注解类型匹配的对象,如果最终没找到,则抛出异常。

CallAdapter是HttpServiceMethod的实现类:

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
                Converter<ResponseBody, ResponseT> responseConverter,
                CallAdapter<ResponseT, ReturnT> callAdapter) {
        super(requestFactory, callFactory, responseConverter);
        this.callAdapter = callAdapter;
    }

    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
        // 调用请求适配器的adapt方法
        return callAdapter.adapt(call);
    }
}
查看其父类HttpServiceMethod中的invoke的实现:

HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
                  Converter<ResponseBody, ResponseT> responseConverter) {
    this.requestFactory = requestFactory;
    this.callFactory = callFactory;
    this.responseConverter = responseConverter;
}

@Override
final @Nullable
ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
}

在代理对象的InvocationHandler中的invoke方法中我们获取到ServiceMethod对象后调用了它的invoke方法,在invoke方法内部可以看到,首先先通过传入RequestFactory、参数、适配器等构建一个OkHttpCall对象,再调用了adapt方法传入OkHttpCall和参数,看回CallAdapter中的adapt方法,所以最终调用了网络请求适配器的adapt方法。

查看DefaultCallAdapterFactory的get方法中返回的匿名CallAdapter对象:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    private final @Nullable
    Executor callbackExecutor; // 回调执行器

    DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public @Nullable
    CallAdapter<?, ?> get(
            Type returnType, Annotation[] annotations, Retrofit retrofit) {
        ...

        return new CallAdapter<Object, Call<?>>() {
            @Override
            public Type responseType() {
                return responseType;
            }

            @Override
            public Call<Object> adapt(Call<Object> call) {
                return executor == null ? call: new ExecutorCallbackCall<>(executor, call);
            }
        };
    }

可以看到在adapt方法中通过传入了回调执行器和OkHttpCall对象构建了ExecutorCallbackCall对象:

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback<T> callback) {
        checkNotNull(callback, "callback == null");

        // 执行请求
        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(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                    }
                });
            }

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

这里我们之前说过,主要是调用了OkHttpCall的enqueue方法后在其回调用了Handler切换线程,那现在我们看下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;
    
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;
    
          call = rawCall;
          failure = creationFailure;
          if (call == null && failure == null) {
            try {
              call = rawCall = createRawCall(); // 赋值得到实际进行请求的Call对象
            } catch (Throwable t) {
              throwIfFatal(t);
              failure = creationFailure = t;
            }
          }
        }
    
        if (failure != null) {
          callback.onFailure(this, failure);
          return;
        }
    
        if (canceled) {
          call.cancel();
        }
    
        // 调用OkHttp的Call对象的enqueue方法
        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) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
    
          @Override public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }
    
          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
      }
}

整理下流程:

1、判断当前是否创建过OkHttp的Call对象了,如果没有,则调用createRawCall方法创建
2、判断当前请求是否取消,如果已取消,则直接调用Call对象的cancel方法后return
3、调用Call的enqueue方法,对它的回调进行处理,这里注意下parseResponse方法

createRawCall方法:

private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
        throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

明显,就是通过OkHttp的newCall方法,通过传入之前创建的RequestFactory对象来构建真正用于请求的Okhttp的Call对象。

parseResponse方法:

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

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
        T body = responseConverter.convert(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;
    }
}

OkHttp的返回的Response对象进行错误码判断,然后调用responseConverter数据转换器的convert对ResponseBody进行数据转换,将得到的数据再转成Retrofit的Response对象(数据在body属性)后返回。

总结

Retrofit通过注解的方式配置请求方式、Header等网络请求参数,简化了请求的构建,同时又提供了CallAdapterConverterAdapter适配器,方便扩展,可对返回的数据进行处理。通过使用动态代理的方式,将请求动态地处理解析成Http参数,交由OkHttp再进行实际请求。最后,用一张图来回顾下基本的流程:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值