阅读 698

Android源码系列-解密Retrofit

Retrofit是什么?

简介

Retrofit,中文的翻译为“式样翻新”的意思,是一个基于OKHttp的RESTful网络请求框架。通俗一点来说,Retrofit就是一个网络请求框架的封装。同样是由Square公司开源的Android热门网络框架之一,其具有功能强大、简洁易用及高可拓展性特点。

官网网址:Retrofit官网

Github地址:Github

特点

1、基于OkHttp并遵循Restful API设计风格

2、通过注解的形式,可简便的配置网络请求参数

3、支持同步及异步的网络请求方式

4、支持RxJava

5、支持多种数据格式的解析(Json、XML、Protobuf等)

Retrofit怎么用?

1、gradle引入库

implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0' //配置使用Gson解析响应数据 可选
implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0' //配置支持RxJava 可选
复制代码

2、初始化Retrofit对象

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL) //配置baseUrl
                .addConverterFactory(GsonConverterFactory.create()) //配置使用Gson解析响应数据
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //配置支持RxJava
                .build();
复制代码

网络接口定义

public interface WeatherService {
        //使用GET请求 直接返回原始数据
        @GET("weather?location=%E5%98%89%E5%85%B4&output=json&ak=5slgyqGDENN7Sy7pw29IUvrZ")
        Call<ResponseBody> cityNameQueryWeather();
        
        //使用GET请求 返回Json映射对象
        @GET("{weather}?location=%E5%98%89%E5%85%B4&output=json")
        Call<WeatherResp> cityWeatherPath(@Path("weather") String weather, @Query("ak") String ak);
        
       //使用POST请求 支持RxJava返回
        @FormUrlEncoded()
        @POST("{weather}")
        rx.Observable<WeatherResp> cityWeatherPost(@Path("weather") String weather, @Field("ak") String ak, @Field("location") String location, @Field("output") String output);
        
        }
复制代码

同步请求

WeatherService weatherService = retrofit.create(WeatherService.class);
        Call<ResponseBody> responseBodyCall = weatherService.cityNameQueryWeather();
        try {
            Response<ResponseBody> responseBody = responseBodyCall.execute();
            System.out.println("call:" + responseBody.body().string());

        } catch (IOException e) {
            e.printStackTrace();
        }
复制代码

异步请求

 WeatherService weatherService = retrofit.create(WeatherService.class);
        Call<WeatherResp> responseBodyCall = weatherService.cityWeatherPath("weather", "5slgyqGDENN7Sy7pw29IUvrZ");
        responseBodyCall.enqueue(new Callback<WeatherResp>() {
            @Override
            public void onResponse(Call<WeatherResp> call, Response<WeatherResp> response) {
                System.out.println("call:" + response.toString());
            }

            @Override
            public void onFailure(Call<WeatherResp> call, Throwable t) {

            }
        });
复制代码

RxJava支持

 WeatherService weatherService = retrofit.create(WeatherService.class);
        weatherService.rxCityWeatherPost("weather", "5slgyqGDENN7Sy7pw29IUvrZ", "%E5%98%89%E5%85%B4", "json")
                .subscribeOn(Schedulers.io())        //在新线程里面处理网络请求
                .observeOn(AndroidSchedulers.mainThread())  //在主线程里面接受返回的数据
                .subscribe(new rx.Observer<WeatherResp>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(WeatherResp weatherResp) {
                        System.out.println("call:" + weatherResp.toString());
                    }
                });
复制代码

详细的Retrofit的注解配置及各注解的使用,推荐参考

这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

Retrofit核心执行流程是怎样?

关键类功能说明

功能说明
Retrofit 里面包含了很多对象,serviceMethodCache(自定义的接口映射对象集合)、baseUrl(请求地址)、callFactory(默认为OKHttpCall)、converterFactories(数据解析器工厂集合)、callAdapterFactories(Call适配器工厂集合)、callbackExecutor(回调执行,Android平台默认为MainThreadExecutor)使用Builder模型构建
Platform Retrofit中用来管理多平台的方法,支持Android、Java8。通过findPlatform获取对应的平台,同时也初始化了defaultCallAdapterFactory工厂
ServiceMethod 接口映射的网络请求对象,通过动态代理,将自定义接口的标注转换为该对象,将标注及参数生成OkHttp所需的Request对象。Retrofit的create通过动态代理拦截,将每一个自定义接口转换成为一个ServiceMethod对象,并通过通过serviceMethodCache进行缓存。
Call Retrofit定义的网络请求接口,包含execute、enqueue等方法
OkHttpCall Ohttp的Call实现,通过createRawCall得到真正的 okhttp3.Call对象,用于进行实际的网络请求
CallAdapter.Factory CallAdapter的静态工厂,包含get的抽象方法,用于生产CallAdapter对象
ExecutorCallAdapterFactory Android平台默认的CallAdapter工厂,get方法使用匿名内部类实现CallAdapter,返回ExecutorCallbackCall,实现了Call
ExecutorCallbackCall 采用静态代理设计,delegate实际为OkHttpCall,使用callbackExecutor实现回调在主线程中执行
RxJavaCallAdapterFactory Rxjava平台的CallAdapter工厂,get方法返回RxJavaCallAdapter对象
RxJavaCallAdapter Rxjava平台的设配器,返回observable对象
Converter.Factory 数据解析器工厂,用于生产Converter实例
GsonConverterFactory 数据解析工厂实例,返回了GsonResponseBodyConverter数据解析器
GsonResponseBodyConverter Gson的数据解析器,将服务端返回的json对象转换成对应的java模型
Response Retrofit网络请求响应的Response

代码执行流程

image

  1. 通过Build模式构建Retrofit对象
  2. 自定义的接口interface,包含接口方法及相关标注
  3. 执行定义的接口方法
  4. 通过Proxy.newProxyInstance进行动态代理拦截
  5. 通过反射将定义的标注方法解析生成ServiceMethod对象(表示一个网络请求的封装对象)并加入serviceMethodCache队列中,避免重复解析
  6. 创建OkHttpCall对象, 继承了Call接口,桥接okhttp3.Call rawCall
  7. 从Retrofit对象的callAdapterFactories工厂集合获取CallAdapter,并调用adapt方法。如果是默认的使用ExecutorCallAdapterFactory设配返回Call,如果设置了RxJavaCallAdapterFactory,返回observable。
  8. 获取适配器转换后的对象,执行同步请求或者异步请求。
  9. 创建Okhttp的RealCall对象
  10. 通过反射的arg参数,调用serviceMethod.toCall(),构建生成Okhttp的RealCall所需要的Request对象
  11. 通过OkHttp的RealCall执行对应的同步或异步请求
  12. 请求成功,通过parseResponse解析请求参数
  13. 通过数据转换器responseConverter.convert(body),将原始数据转换为对象
  14. 回调解析完的数据对象Respone(T)
  15. Retrofit 如何将定义的interface转换成网络请求?

    我们都知道,Retrofit通过自定义interface及相关的标注来描述一个http的请求,使用非常简便,且易于维护。

    这是Retrofit设计的精髓之一,,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象,ServiceMethod中封装了OKHttp网络请求所需的相关参数。

    源码实现如下:

     public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);
        if (validateEagerly) {
          eagerlyValidateMethods(service);
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
            new InvocationHandler() {
              private final Platform platform = Platform.get();
    
              @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                //生成ServiceMethod
                ServiceMethod<Object, Object> serviceMethod =o
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.adapt(okHttpCall);
              }
            });
      }
    复制代码

    通过源码我们知道,具体的转换方法为 (ServiceMethod<Object, Object>) loadServiceMethod(method),具体的实现如下:

    ServiceMethod<?, ?> loadServiceMethod(Method method) {
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;
    
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    复制代码

    通过Builder构建模式,创建一个ServiceMethod对象,并加入缓存,具体的构造实现如下:

     Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    
        public ServiceMethod build() {
          callAdapter = createCallAdapter();
          responseType = callAdapter.responseType();
          if (responseType == Response.class || responseType == okhttp3.Response.class) {
            throw methodError("'"
                + Utils.getRawType(responseType).getName()
                + "' is not a valid response body type. Did you mean ResponseBody?");
          }
          responseConverter = createResponseConverter();
    
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          if (httpMethod == null) {
            throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
          }
    
          if (!hasBody) {
            if (isMultipart) {
              throw methodError(
                  "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
            }
            if (isFormEncoded) {
              throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
                  + "request body (e.g., @POST).");
            }
          }
    
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0; p < parameterCount; p++) {
            Type parameterType = parameterTypes[p];
            if (Utils.hasUnresolvableType(parameterType)) {
              throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
                  parameterType);
            }
    
            Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
            if (parameterAnnotations == null) {
              throw parameterError(p, "No Retrofit annotation found.");
            }
    
            parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
          }
    
          if (relativeUrl == null && !gotUrl) {
            throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
          }
          if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
            throw methodError("Non-body HTTP method cannot contain @Body.");
          }
          if (isFormEncoded && !gotField) {
            throw methodError("Form-encoded method must contain at least one @Field.");
          }
          if (isMultipart && !gotPart) {
            throw methodError("Multipart method must contain at least one @Part.");
          }
    
          return new ServiceMethod<>(this);
        }
    复制代码

    build()方法会通过反射去解析method的标注、参数的类型等。详细的解析可参考源码ParameterHandler相关实现,这里主要对流程进行剖析。

    总结一下,Retrofit通过自定义interface及相关的标注来描述一个http的请求,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象,ServiceMethod中封装了OKHttp网络请求所需的相关参数。这就是Retrofit将定义的interface转换成网络请求对象的过程。

    Retrofit的Converter机制是如何实现?

    Converter种类

    Retrofit支持多种数据解析方式,使用时需要在Gradle添加依赖。

    数据解析器 Gradle依赖
    Gson com.squareup.retrofit2:converter-gson:2.4.0
    Jackson com.squareup.retrofit2:converter-jackson:2.4.0
    Simple XML com.squareup.retrofit2:converter-simplexml:2.4.0
    Protobuf com.squareup.retrofit2:converter-protobuf:2.4.0
    Moshi com.squareup.retrofit2:converter-moshi:2.4.0
    Wire com.squareup.retrofit2:converter-wire:2.4.0
    Scalars com.squareup.retrofit2:converter-scalars:2.4.0

    Converter实现流程

    添加Converter工厂

    首先在Retrofit的初始化添加Converter,addConverterFactory(GsonConverterFactory.create())。具体实现如下:

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

    将Converter的工厂加入到converterFactories集合中。

    触发数据转换

    通过上述的流程分析,我们知道Retrofit当网络请求成功后会执行,OkHttpCall中的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);
        }
    
        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
          T body = serviceMethod.toResponse(catchingBody);
          return Response.success(body, rawResponse);
        } catch (RuntimeException e) {
          // If the underlying source threw an exception, propagate that rather than indicating it was
          // a runtime exception.
          catchingBody.throwIfCaught();
          throw e;
        }
      }
    复制代码

    其中关键的代码为 T body = serviceMethod.toResponse(catchingBody),具体实现如下:

     /** Builds a method return value from an HTTP response body. */
      R toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }
    复制代码

    数据转换器的创建

    这里就是 Converter实现转换的地方,那么responseConverter在哪里进行初始化呢?在ServiceMethod的Build方法中,会调用createResponseConverter()进行数据解析器的创建,实现如下:

     private Converter<ResponseBody, T> createResponseConverter() {
          Annotation[] annotations = method.getAnnotations();
          try {
            return retrofit.responseBodyConverter(responseType, annotations);
          } catch (RuntimeException e) { // Wide exception range because factories are user code.
            throw methodError(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);
      }
    
    复制代码

    调用了 retrofit.nextResponseBodyConverter方法

     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());
      }
    复制代码

    通过Retrofit的converterFactories工厂集合匹配获取开始添加的数据转换工厂

    默认的数据转换工厂

    通过Retrofit build() 中发现如下代码,converterFactories.add(new BuiltInConverters()),可知Retrofit默认的数据转换器工厂为BuiltInConverters。主要实现如下:

     @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        if (type == ResponseBody.class) {
          return Utils.isAnnotationPresent(annotations, Streaming.class)
              ? StreamingResponseBodyConverter.INSTANCE
              : BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) {
          return VoidResponseBodyConverter.INSTANCE;
        }
        return null;
      }
    
    复制代码

    会将数据转换为ResponseBody对象,所以如果Retrofit默认不使用任何数据解析器,定义interface方法时接收数据对象使用 Call。

    Retrofit的CallAdapter机制是如何实现?

    Retrofit支持多种网络请求适配器方式:guava、Java8和rxjava 。Android默认的适配器工厂为ExecutorCallAdapterFactory,最后的回调通过ExecutorCallbackCall切换至主线程运行。

    CallAdapter种类

    网络请求适配器 Gradle依赖
    guava com.squareup.retrofit2:adapter-guava:2.4.0
    Java8 com.squareup.retrofit2:adapter-java8:2.4.0
    rxjava com.squareup.retrofit2:adapter-rxjava:2.4.0

    CallAdapter实现流程

    添加CallAdapter工厂

    首先在Retrofit的初始化添加CallAdapter工厂,addCallAdapterFactory(RxJavaCallAdapterFactory.create())。具体实现如下:

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

    将CallAdapter的工厂加入到callAdapterFactories集合中。

    CallAdapter的adapt实现

    通过上述Retrofit的create方法中分析可知,当拦截到interface的方法调用后最后会执行 return serviceMethod.adapt(okHttpCall)。adapt的实现如下:

      T adapt(Call<R> call) {
        return callAdapter.adapt(call);
      }
    复制代码

    就是在这个地方触发了callAdapter的adapt方法。返回最终适配的具体对象。

    默认的CallAdapter工厂

    Android平台默认的CallAdapter工厂为ExecutorCallAdapterFactory。通过Retrofit的build()方法可知:

     // Make a defensive copy of the adapters and add the default Call adapter.
          List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
          callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    复制代码

    platform.defaultCallAdapterFactory的实现如下:

     CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        if (callbackExecutor != null) {
          return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        return DefaultCallAdapterFactory.INSTANCE;
      }
    复制代码

    ExecutorCallAdapterFactory的CallAdapter创建如下:

     public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
            if (getRawType(returnType) != Call.class) {
                return null;
            } else {
                final Type responseType = Utils.getCallResponseType(returnType);
                return new CallAdapter<Object, Call<?>>() {
                    public Type responseType() {
                        return responseType;
                    }
    
                    public Call<Object> adapt(Call<Object> call) {
                        return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
                    }
                };
            }
        }
    复制代码

    adapt方法最后返回还是Call对象,具体的适配实现由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;
            }
    
            public void enqueue(final Callback<T> callback) {
                Utils.checkNotNull(callback, "callback == null");
                this.delegate.enqueue(new Callback<T>() {
                    public void onResponse(Call<T> call, final Response<T> response) {
                        ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
                            public void run() {
                                if (ExecutorCallbackCall.this.delegate.isCanceled()) {
                                    callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                                } else {
                                    callback.onResponse(ExecutorCallbackCall.this, response);
                                }
    
                            }
                        });
                    }
    
                    public void onFailure(Call<T> call, final Throwable t) {
                        ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
                            public void run() {
                                callback.onFailure(ExecutorCallbackCall.this, t);
                            }
                        });
                    }
                });
            }
    
           
    
            public Response<T> execute() throws IOException {
                return this.delegate.execute();
            }
    }
    复制代码

    具体的执行还是通过delegate(OkHttpCall)来执行,但是在回调使用了 ExecutorCallbackCall.this.callbackExecutor.execute()方法,Android平台的callbackExecutor实现为MainThreadExecutor。具体源码如下:

    static class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override public void execute(Runnable r) {
            handler.post(r);
          }
        }
    复制代码

    所以ExecutorCallAdapterFactory中适配最后的设配对象还是Call,实现还是OkHttpCall,通过 MainThreadExecutor,将回调切换在UI线程中运行

    CallAdapter的创建

    在ServiceMethod的Build方法中,createCallAdapter()进行适配器的的创建,实现如下:

      private CallAdapter<T, R> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          if (Utils.hasUnresolvableType(returnType)) {
            throw methodError(
                "Method return type must not include a type variable or wildcard: %s", returnType);
          }
          if (returnType == void.class) {
            throw methodError("Service methods cannot return void.");
          }
          Annotation[] annotations = method.getAnnotations();
          try {
            //noinspection unchecked
            return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
          } catch (RuntimeException e) { // Wide exception range because factories are user code.
            throw methodError(e, "Unable to create call adapter for %s", returnType);
          }
        }
    复制代码

    调用了 retrofit.callAdapter

      public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
       return nextCallAdapter(null, returnType, annotations);
     }
    复制代码

    调用了 retrofit.nextCallAdapter

     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());
     }
    复制代码

    通过Retrofit的callAdapterFactories工厂集合匹配获取开始添加的适配器工厂

    如何自定义一个Converter及CallAdapter?

    自定义Converter

    1、需要定义一个工厂类继承Converter.Factory

    2、复写responseBodyConverter及requestBodyConverter方法

    3、在Retrofit定义时加入自定义的Converter,addConverterFactory(new CustomConverterFactory())

    /**
     * @author allen
     * @date 2018/8/7
     * 返回服务端返回的string结果
     */
    public class CustomConverterFactory extends Converter.Factory {
    
        @Nullable
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return StringResponseBodyConverter.INSTANCE;
        }
        @Nullable
        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return StringRequestBodyConverter.INSTANCE;
        }
    
        static final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
            static final CustomConverterFactory.StringResponseBodyConverter INSTANCE = new CustomConverterFactory.StringResponseBodyConverter();
    
            @Override
            public String convert(ResponseBody value) {
    
                try {
                    System.out.println("CustomConverterFactory");
                    return value.string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return "";
            }
        }
        static final class StringRequestBodyConverter implements Converter<RequestBody, RequestBody> {
            static final CustomConverterFactory.StringRequestBodyConverter INSTANCE = new CustomConverterFactory.StringRequestBodyConverter();
    
            @Override
            public RequestBody convert(@NonNull RequestBody value) {
                return value;
            }
        }
    }
    复制代码

    自定义CallAdapter

    1、需要定义一个工厂类继承CallAdapter.Factory

    2、复写CallAdapter get方法

    3、在Retrofit定义时加入自定义的CallAdapter, addCallAdapterFactory(new CustomCallAdapterFactory())

    /**
     * @author allen
     * @date 2018/8/7
     */
    public class CustomCallAdapterFactory extends CallAdapter.Factory {
        @Nullable
        @Override
        public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    
            return new CallAdapter<Object, Object>() {
                @Override
                public Type responseType() {
                    return String.class;
                }
    
                @Override
                public Object adapt(Call<Object> call) {
                    System.out.println("CustomCallAdapterFactory adapt(");
                    return call;
                }
            };
        }
    }
    
    复制代码

    Retrofit中运用了那些设计模式?

    1、建造者模式

    Retrofit对象的创建、ServiceMethod对象创建都使用Build模式,将复杂对象的创建和表示分离,调用者不需要知道复杂的创建过程,使用Build的相关方法进行配置创建对象。

    2、外观模式

    Retrofit对外提供了统一的调度,屏蔽了内部的实现,使得使用该网络库简单便捷。

    3、动态代理模式

    通过动态代理的方式,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象。

    4、静态代理模式 Android平台默认的适配器ExecutorCallbackCall,采用静态代理的模式。具体的实现delegate为OkHttpCall。

    5、工厂模式 Converter及CallAdapter的创建都采用了工厂模式进行创建。

    6、适配器模式 CallAdapter的adapt采用了适配器模式,使得interface的返回对象可以动态扩展,增强了灵活性

    总结

    思考

    大多数流行的开源框架都是经过顶级coder的设计,包含了很多精妙的设计。多学习分析,收益良多。

    参考资料

    这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)

    Android:手把手带你深入剖析 Retrofit 2.0 源码

    推荐

    Android源码系列-解密OkHttp

    Android源码系列-解密Retrofit

    Android源码系列-解密Glide

    Android源码系列-解密EventBus

    Android源码系列-解密RxJava

    Android源码系列-解密LeakCanary

    Android源码系列-解密BlockCanary

    关于

    欢迎关注我的个人公众号

    微信搜索:一码一浮生,或者搜索公众号ID:life2code

    image