Android之网络—第四篇(解读Retrofit)

前言:这篇网络系列的初衷是分享下网络相关的知识,文章属于个人的学习总结博客。部分内容来源网络,如有不适,请私聊。

Android之网络—第一篇(Http原理)
Android之网络—第二篇(Https原理)
Android之网络—第三篇(解读OkHttp)
Android之网络—第四篇(解读Retrofit)

详解网络封装艺术之Retrofit

前面大概分析了下OkHttp,知道OkHttp更多的是网络的底层实现。使用起来的话,还需要各种定制化的配置,以及数据的解析,数据回调的线程线程切换等问题。但是这些问题在Retrofit中得到了更好的支持,Retrofit通过使用大量的设计模式很好解耦和封装了网络请求,使用起来更加舒适。
retrofit源码地址

简单介绍下Retrofit的使用

可以看看官网的实例介绍,链接地址:http://square.github.io/retrofit/

第一步,定义一个接口,并通过注解定义对应的Api实现。
public interface GithubService {

    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

第二步,配置Retrofit对象,并创建接口对象
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

第三步,调用Api,传入实际参数,并开始请求
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(new Callback<List<Repo>>() {
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
                System.out.println("response:"+response.body().get(0).getName());
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
            }
        });

这里的使用需要注意的点:定义接口通过注解定义对应的Api实现时,不同的注解有不同的使用方式。下面简单分析下。
上面通过注解@GET和@Path将真正的请求连接https://api.github.com/users/octocat/repos分别分割拼装起来了。Url = baseUrl() + path (完整URL = 基础域名 + 注解配置)

Retrofit注解说明
第一类:网络请求方法类型
  • a、@GET、@POST、@PUT、@DELETE、@HEAD、@OPTIONS 分别对应HTTP请求头的[Method]
  • b、@HTTP 用于替换上述七种方式,可以通过属性methodpathhasBody进行设置。例如:
public interface GithubService {
    @HTTP(method = "GET", path = "users/{user}/repos", hasBody = false)
    Call<List<Repo>> listRepos(@Path("user") String user);
}
第二类:标记类型,用于区分数据类型,对应HTTP的Content-Type类型
  • a、@FormUrlEncoded 表示以普通表单类型提交数据,参数键值对需要用@Filed设置。例如:
public interface GithubService {
    @FormUrlEncoded
    @POST("user/edit")
    Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
}
  • b、@Multipart 表示以多媒体类型提交数据,参数键值对需要用@Part设置。例如:
public interface GithubService {
    @Multipart
    @PUT("user/photo")
    Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
}
第三类:请求参数类型,用于拼装请求参数
  • a、@Header & @Headers 添加请求头。例如:
public interface GithubService {
    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)

    @Headers({
            "Accept: application/vnd.github.v3.full+json",
            "User-Agent: Retrofit-Sample-App"
    })
    @GET("users/{username}")
    Call<User> getUser(@Path("username") String username);

    // 区别在于使用场景和使用方式:
    // 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
    // 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
}
public interface GithubService {

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);

    @GET("group/{id}/users")
    Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
}
  • d、@Field & @FieldMap 用于@FormUrlEncoded 提交数据类型,拼接参数。例如:
public interface GithubService {
    @FormUrlEncoded
    @POST("user/edit")
    Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

    @FormUrlEncoded
    @POST("user/edit")
    Call<User> updateUser(@FieldMap Map<String, Object> map);
}
  • e、@Part & @PartMap 用于@Multipart提交数据类型,拼接参数。例如:
public interface GithubService {
    @Multipart
    @PUT("user/photo")
    Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

    @Multipart
    @PUT("user/photo")
    Call<User> updateUser(@PartMap Map<String, RequestBody> args);
}
  • f、@Body 用于以 Post方式 传递自定义数据类型给服务器。例如:
public interface GithubService {
    @POST("users/new")
    Call<User> createUser(@Body User user);
}

源码解读Retrofit

public class Demo{
    Retrofit retrofit = new Retrofit.Builder().build();
    GitHubService service = retrofit.create(GitHubService.class);
    Call<List<Repo>> repos = service.listRepos("octocat").enqueue();
}

回归最开始的示例,让我们一步一步地去探究源码的实现吧

第一部分:Retrofit网络请求流程分析

(1)、动态代理调用ServerInterface接口

PS:动态代理可参考文章:说说 Java 代理模式

public final class Retrofit {
    .....
    public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service); //判断是否是接口类型
        if (validateEagerly) { //是否预先加载ServiceInterface内的Api
            eagerlyValidateMethods(service); 
        }
        //通过动态代理加载Api接口
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
                new InvocationHandler() {
                    private final Platform platform = Platform.get(); //平台 android / java8
                    private final Object[] emptyArgs = new Object[0];
    
                    @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) { //如果是Object对象的方法直接调用
                            return method.invoke(this, args);
                        }
                        if (platform.isDefaultMethod(method)) {
                            return platform.invokeDefaultMethod(method, service, proxy, args);
                        }
                        //通过ServerInterface的接口
                        return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                    }
                });
    }
    
    ServiceMethod<?> loadServiceMethod(Method method) {
        //内置一个缓存Map来缓存ServerInterface的接口
        ServiceMethod<?> result = serviceMethodCache.get(method); //返回一个ServiceMethod对象
        if (result != null) return result;
    
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = ServiceMethod.parseAnnotations(this, method);
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }
    .....
}

通过上述的源码分析发下,Retrofit 通过动态代理的方式调用ServerInterface接口实现。但是invoke()的具体调用又在哪里呢?

(2)、ServiceMethod解析注解并返回核心封装类HttpServiceMethod()
abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        //通过RequestFactory将Api的注解解析成完整的请求连接
        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.");
        }
        //传入解析后的requestFactory并返回具体子类对象
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }
    //抽象类,通过子类实现
    abstract T invoke(Object[] args);
}

通过这里可以发现,ServiceMethod主要通过RequestFactory将注解解析成完整的请求格式,并返回子类HttpServiceMethod对象。

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

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
            Retrofit retrofit, Method method, RequestFactory requestFactory) {

        //返回适配器对象
        CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);

        //异常判断
        Type responseType = callAdapter.responseType();
        if (responseType == Response.class || responseType == okhttp3.Response.class) {
            throw methodError(method, "'"
                    + Utils.getRawType(responseType).getName()
                    + "' is not a valid response body type. Did you mean ResponseBody?");
        }
        if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
            throw methodError(method, "HEAD method must use Void as response type.");
        }
      
        //返回数据解析器对象
        Converter<ResponseBody, ResponseT> responseConverter =
                createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory;  //实际默认创建一个new OkHttpClient()实例
        return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
    }
    ......

    //callAdapter.adapt() 返回的就是Call对象。
    @Override ReturnT invoke(Object[] args) {
        return callAdapter.adapt(
                new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
    }
}
(3)、网络请求具体实现OkHttpCall()
final class OkHttpCall<T> implements Call<T> {
    ......
    //网络的同步请求
    @Override 
    public Response<T> execute() throws IOException {
        okhttp3.Call call;

        synchronized (this) {
            //一大段的异常判断
            if (executed) throw new IllegalStateException("Already executed.");
            executed = true;

            if (creationFailure != null) {
                if (creationFailure instanceof IOException) {
                    throw (IOException) creationFailure;
                } else if (creationFailure instanceof RuntimeException) {
                    throw (RuntimeException) creationFailure;
                } else {
                    throw (Error) creationFailure;
                }
            }

            call = rawCall;
            if (call == null) {
                try {
                    call = rawCall = createRawCall(); //创建OkHttpClient请求
                } catch (IOException | RuntimeException | Error e) {
                    throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
                    creationFailure = e;
                    throw e;
                }
            }
        }
        //取消请求
        if (canceled) {
            call.cancel();
        }
        //返回请求结果,实际就是client.newCall(request).execute()发送请求
        return parseResponse(call.execute());
    }
    ......

    //发送异步请求
    @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(); //创建OkHttpClient请求
                } catch (Throwable t) {
                    throwIfFatal(t);
                    failure = creationFailure = t;
                }
            }
        }

        if (failure != null) {
            callback.onFailure(this, failure);
            return;
        }
        //取消请求
        if (canceled) {
            call.cancel();
        }

        //OkHttp发送异步请求,并返回结果
        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) {
                    t.printStackTrace();
                }
            }

            @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) {
                    t.printStackTrace();
                }
            }
        });
    }
    ......
    //实际返回的就是OkHttp的RealCall对象,callFactory为OkHttpClient
    private okhttp3.Call createRawCall() throws IOException {
        //将注解的请求信息requestFactory,拼接到OkHttp配置里
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
        if (call == null) {
            throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
    }
    .......
}

到这里就整体发现Retrofit的网络请求是通过封装OkHttp去做底层的请求的。整体的网络请求流程就分析完毕了。但是也没感觉到封装艺术的魅力呀。

第二部分:Retrofit封装艺术的魅力

前文介绍Retrofit时,注意赞美的词的关键点哈:处理繁琐的定制化的配置,随心所欲的定制化数据的解析,便捷的线程切换。但是,通过上面整个网络请求的分析,怎么没感觉到呢?

先来看看上面分析流程的几个关键点:

//1、通过RequestFactory将Api的注解解析成完整的请求连接
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

//2、获取并传入一系列初始化对象
new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);

//3、通过适配器转换,做不同的线程策略切换
callAdapter.adapt(new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));

//4、通过适配器转换,完成不同类型数据解析
response = parseResponse(rawResponse);

通过这几个关键点的分析,似乎好像触摸到什么有趣的东西哈。

  • 第一点可以自动化的解析注解的配置,在写请求时就不需要关心繁琐的配置啦
  • 第三点通过适配转化,就可以自动化完成线程的切换,在写请求时直接才主线程请求,数据也可以直接返回主线程啦
  • 第四点通过适配转化,就可以将服务端请求的字节流请求转化为对应的数据格式,在写请求时直接解析数据就可以啦。
(1)Retrofit整体的网络架构图
image.png

架构图分析说明:


Retrofit分析图解.png

注意:上图的关键关于适配器模式部分,需要结合官方推荐的一起看,在Gradle添加依赖。

  • 请求适配器(CallAdapter)

Java8 : com.squareup.retrofit2:adapter-java8:2.0.2
Guava : com.squareup.retrofit2:adapter-guava:2.0.2
Rxjava : com.squareup.retrofit2:adapter-rxjava:2.0.2

  • 数据解析器(Converter)

Gson : com.squareup.retrofit2:converter-gson:2.0.2
Jackson : com.squareup.retrofit2:converter-jackson:2.0.2
Simple XML : com.squareup.retrofit2:converter-simplexml:2.0.2
Protobuf : com.squareup.retrofit2:converter-protobuf:2.0.2
Moshi : com.squareup.retrofit2:converter-moshi:2.0.2
Wire : com.squareup.retrofit2:converter-wire:2.0.2
Scalars : com.squareup.retrofit2:converter-scalars:2.0.2

(2)结合源码分析整体架构

通过整体架构分析发现,关键点的地方有三个:

  • 1、CreateServerMethod() 这里为请求做准备工作都具体做了什么?
  • 2、CallAdapter.Factory 这里是如何通过代码结构做到框架的适配转化?
  • 3、Converter.Factory 这里是如何通过代码结构做到不同数据的适配的?
(1)、准备工作之解析注解
final class RequestFactory {
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
    }
    ......
    RequestFactory build() {
         //遍历注解并解析
        for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
        }
        //一堆的异常判断
        ......
        return new RequestFactory(this);
    }    
    ......
    //根据请求头的Method注解分别对应解析
    private void parseMethodAnnotation(Annotation annotation) {
        if (annotation instanceof 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) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
                throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
        } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
                throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true; //将Multipart标记
        } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
                throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true; //将FormEncod标记
        }
    }    
}

总结来说,RequestFactory内部通过遍历注解,根据请求的Method的类型分别将网络注解参数获取并拼接,提供给OkHttp发起请求时直接用。

(2)、准备工作之请求适配器(CallAdapter)与 数据解析器(Converter)

请求适配器(CallAdapter)的基本代码结构:

public interface CallAdapter<R, T> {
    .....
    //将传进来的Call转化为另一个Call
    T adapt(Call<R> call);

    //定义抽象接口,用于标记持有适配器对象
    abstract class Factory {
        public abstract CallAdapter<?, ?> get(); //返回一个适配器
    }
}

自定义的适配器对象:

class CustomCallAdapterFactory extends CallAdapter.Factory {
    @Override 
    public @Nullable CallAdapter<?, ?> get(){
        return new CallAdapter<Object, Call<?>>(){
            @Override 
            public Call<Object> adapt(Call<Object> call) {
                //将真正的Call传进来,包装成另外一个Call后完成请求,并做线程切换
            }
        };
    }
}

数据解析器(Converter)的基本代码结构:

public interface Converter<R, T> {
    .....
    //将解析的结果返回
   T convert(F value) throws IOException;

    //定义抽象接口,用于标记持有解析器对象
    abstract class Factory {
        //解析为Response
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }
        //解析为Request
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
                                                              Annotation[] methodAnnotations, Retrofit retrofit) {
            return null;
        }
        //解析为String类型数据
        public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return null;
        }
    }
}

自定义的适配器对象:

class CustomConverterFactory extends Converter.Factory {
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new CustomResponseBodyConverter<>();
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, 
                                    Annotation[] methodAnnotations, Retrofit retrofit) {
        return new CustomRequestBodyConverter<>();
    }
}

来看看Retrofit的源码默认的实现

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

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
            Retrofit retrofit, Method method, RequestFactory requestFactory) {
        CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
        ......
        Converter<ResponseBody, ResponseT> responseConverter =
                createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory;
        return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
    }

    private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
            Retrofit retrofit, Method method) {
        Type returnType = method.getGenericReturnType();
        Annotation[] annotations = method.getAnnotations();
        try {
            //noinspection unchecked
            //通过retrofit实例返回一个适配器
            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);
        }
    }

    private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
            Retrofit retrofit, Method method, Type responseType) {
        Annotation[] annotations = method.getAnnotations();
        try {
            //返回一个responseBody的数据解析器
            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的具体实现

public final class Retrofit {
    ......
    public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
    }

    public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, 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++) {
            //遍历List,根据Type 找到配置的对应的适配器
            CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
            if (adapter != null) {
                return adapter;
            }
        }
         //如果都没有就抛异常
        .......
        throw new IllegalArgumentException(builder.toString());
    }

    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;
            }
        }
         //如果都没有就抛异常
        .......
        throw new IllegalArgumentException(builder.toString());
    }
    ......
    
    public Retrofit build() {
        if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
        }

        okhttp3.Call.Factory callFactory = this.callFactory;
        if (callFactory == null) {
            callFactory = new OkHttpClient();  //创建一个OkHttpClient实例
        }

        //在后面的分析中,特别要注意platform这个对象,默认实现有android和Java8
        Executor callbackExecutor = this.callbackExecutor;
        if (callbackExecutor == null) {
            // Retrofit默认的platform有android 和 java8
            // android 创建一个默认的MainThreadExecutor()
            // Java8默认为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()); //24以下,默认为空

        return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
                unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
}

总结来说,HttpServiceMethod初始化的对象在Retrofit对象创建的时候就通过build()默认根据platform的特性实例化了对饮的默认对象。

Retrofit默认实现的适配器(CallAdapter)对象

static class Android extends Platform {
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
            @Nullable Executor callbackExecutor) {
        if (callbackExecutor == null) throw new AssertionError();
        ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
        return Build.VERSION.SDK_INT >= 24
                ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
                : singletonList(executorFactory);
    }
}
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    ......
    @Override 
    public @Nullable CallAdapter<?, ?> get(
            Type returnType, Annotation[] annotations, Retrofit retrofit) {

        return new CallAdapter<Object, Call<?>>() {
            ......
            @Override public Call<Object> adapt(Call<Object> call) {
                return new ExecutorCallbackCall<>(callbackExecutor, call); //返回一个封装的Call
            }
        };
    }

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate; //实际上就是传进来的OkHttpCall
        // 通过enqueue、execute封装让OkHttpCall发送请求
        @Override 
        public void enqueue(final Callback<T> callback) {
            delegate.enqueue(new Callback<T>() {
                @Override 
                public void onResponse(Call<T> call, final Response<T> response) {
                    callbackExecutor.execute(new Runnable() { //通过MainHandler将结果返回主线程
                        @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() { //通过MainHandler将结果返回主线程
                        @Override 
                        public void run() {
                            callback.onFailure(ExecutorCallbackCall.this, t);
                        }
                    });
                }
            });
        }
        
        @Override 
        public Response<T> execute() throws IOException {
            return delegate.execute();
        }
   
    }
}

Retrofit默认实现的数据解析器(Converter)对象集合

final class BuiltInConverters extends Converter.Factory {
    /** Not volatile because we don't mind multiple threads discovering this. */
    private boolean checkForKotlinUnit = true;

    @Override
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
            Type type, Annotation[] annotations, Retrofit retrofit) {
        if (type == ResponseBody.class) { 
            //判断注解类型是否是@Streaming
            //是,以数据流的形式返回,
            return Utils.isAnnotationPresent(annotations, Streaming.class)
                    ? StreamingResponseBodyConverter.INSTANCE
                    : BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) { //为空类型,返回null
            return VoidResponseBodyConverter.INSTANCE;
        }
        if (checkForKotlinUnit) {
            try {
                if (type == Unit.class) { //暂时不清楚Unit类型
                    return UnitResponseBodyConverter.INSTANCE;
                }
            } catch (NoClassDefFoundError ignored) {
                checkForKotlinUnit = false;
            }
        }
        return null; //默认为空
    }

    @Override
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, 
                                                                    Annotation[] methodAnnotations, Retrofit retrofit) {
        if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
            return RequestBodyConverter.INSTANCE;
        }
        return null;
    }

    static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
        static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

        @Override
        public Void convert(ResponseBody value) {
            value.close();
            return null;
        }
    }

    static final class UnitResponseBodyConverter implements Converter<ResponseBody, Unit> {
        static final UnitResponseBodyConverter INSTANCE = new UnitResponseBodyConverter();

        @Override
        public Unit convert(ResponseBody value) {
            value.close();
            return Unit.INSTANCE;
        }
    }

    static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
        static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

        @Override
        public RequestBody convert(RequestBody value) {
            return value;
        }
    }

    static final class StreamingResponseBodyConverter
            implements Converter<ResponseBody, ResponseBody> {
        static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

        @Override
        public ResponseBody convert(ResponseBody value) {
            return value;
        }
    }

    static final class BufferingResponseBodyConverter
            implements Converter<ResponseBody, ResponseBody> {
        static final BufferingResponseBodyConverter INSTANCE = new 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();
            }
        }
    }

    static final class ToStringConverter implements Converter<Object, String> {
        static final ToStringConverter INSTANCE = new ToStringConverter();

        @Override
        public String convert(Object value) {
            return value.toString();
        }
    }
}

总结来说,Retrofit默认实现一个数据转化器,用来将OkHttp请求的结果通过MainHandler将结果转发到主线程,而默认数据解析器,如果配置了注解@Streaming,则结果返回时,以数据流的形式返回,不然按OkHttp原生解析的形式返回。

后序:这篇文章从源码角度整体分析Retrofit,适配器模式的应用很精妙,在网络封装方面可以很好的借鉴哦。

如果觉得我的文章对你有帮助,请随意赞赏。您的支持将鼓励我继续创作!

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