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<T> 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<T> Retrofit网络请求响应的Response

代码执行流程

image
  1. 通过Build模式构建Retrofit对象
  2. 自定义的接口interface,包含接口方法及相关标注
  3. 执行定义的接口方法
  4. 通过Proxy.newProxyInstance进行动态代理拦截
  5. 通过反射将定义的标注方法解析生成ServiceMethod对象(表示一个网络请求的封装对象)并加入serviceMethodCache队列中,避免重复解析
  6. 创建OkHttpCall对象, 继承了Call<T>接口,桥接okhttp3.Call rawCall
  7. 从Retrofit对象的callAdapterFactories工厂集合获取CallAdapter,并调用adapt方法。如果是默认的使用ExecutorCallAdapterFactory设配返回Call<Object>,如果设置了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)

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<ResponseBody>。

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<Object>对象,具体的适配实现由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<Object>,实现还是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

关于

欢迎关注我的个人公众号

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

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

推荐阅读更多精彩内容