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> 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> repos = service.listRepos("octocat");
repos.enqueue(new Callback>() {
            @Override
            public void onResponse(Call> call, Response> response) {
                System.out.println("response:"+response.body().get(0).getName());
            }

            @Override
            public void onFailure(Call> 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> listRepos(@Path("user") String user);
}
第二类:标记类型,用于区分数据类型,对应HTTP的Content-Type类型
  • a、@FormUrlEncoded 表示以普通表单类型提交数据,参数键值对需要用@Filed设置。例如:
public interface GithubService {
    @FormUrlEncoded
    @POST("user/edit")
    Call updateUser(@Field("first_name") String first, @Field("last_name") String last);
}
  • b、@Multipart 表示以多媒体类型提交数据,参数键值对需要用@Part设置。例如:
public interface GithubService {
    @Multipart
    @PUT("user/photo")
    Call updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
}
第三类:请求参数类型,用于拼装请求参数
  • a、@Header & @Headers 添加请求头。例如:
public interface GithubService {
    @GET("user")
    Call getUser(@Header("Authorization") String authorization)

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

    // 区别在于使用场景和使用方式:
    // 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
    // 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
}
  • b、@Path 替换Url地址的缺省值。

  • c、@Query和@QueryMap 用于GET请求拼接?后的Key-Value参数。格式:https://www.baidu.com/?tn=98012088_10_dg&ch=3 例如:

public interface GithubService {

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

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

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

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

源码解读Retrofit

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

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

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

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

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

public final class Retrofit {
    .....
    public  T create(final Class 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 {
    static  ServiceMethod 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 extends ServiceMethod {

    static  HttpServiceMethod parseAnnotations(
            Retrofit retrofit, Method method, RequestFactory requestFactory) {

        //返回适配器对象
        CallAdapter 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 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 implements Call {
    ......
    //网络的同步请求
    @Override 
    public Response 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 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 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整体的网络架构图
Android之网络—第四篇(解读Retrofit)_第1张图片
image.png

架构图分析说明:


Android之网络—第四篇(解读Retrofit)_第2张图片
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 {
    .....
    //将传进来的Call转化为另一个Call
    T adapt(Call call);

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

自定义的适配器对象:

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

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

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

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

自定义的适配器对象:

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

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

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

final class HttpServiceMethod extends ServiceMethod {

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

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

    private static  CallAdapter createCallAdapter(
            Retrofit retrofit, Method method) {
        Type returnType = method.getGenericReturnType();
        Annotation[] annotations = method.getAnnotations();
        try {
            //noinspection unchecked
            //通过retrofit实例返回一个适配器
            return (CallAdapter) 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  Converter 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  Converter 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  Converter 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 converter =
                    converterFactories.get(i).responseBodyConverter(type, annotations, this);
            if (converter != null) {
                //noinspection unchecked
                return (Converter) 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 callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
        callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

        // Make a defensive copy of the converters.
        List 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 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>() {
            ......
            @Override public Call adapt(Call call) {
                return new ExecutorCallbackCall<>(callbackExecutor, call); //返回一个封装的Call
            }
        };
    }

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

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

    static final class UnitResponseBodyConverter implements Converter {
        static final UnitResponseBodyConverter INSTANCE = new UnitResponseBodyConverter();

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

    static final class RequestBodyConverter implements Converter {
        static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

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

    static final class StreamingResponseBodyConverter
            implements Converter {
        static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

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

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

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

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

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

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

你可能感兴趣的:(Android之网络—第四篇(解读Retrofit))