Android Retrofit 原理解析

Android Retrofit 原理解析

  • 一.基本使用
  • 二.源码分析
    • 1.Retrofit.Builder构建参数
    • 2.可配置项
      • (1)CallFactory
      • (2)ConverterFactory
      • (3)CallAdapterFactory
      • (4)CallbackExecutor
    • 3.Retrofit.create动态代理生成请求对象
    • 4.ServiceMethod
      • (1)创建
      • (2)解析方法注解
      • (3)解析参数注解
      • (4)请求时构建出完整的Request对象
      • (5)请求回来后将ResponseBody转换为结果类型
    • 5.OkHttpCall
    • 6.CallAdapter包装返回类型
    • 7.cancel
  • 三.结合RXJava
    • 1.RXJavaCallAdapter
      • (1)RXJavaCallAdapterFactory
      • (2)RXJavaCallAdapter
    • 2.简单使用

一.基本使用

先来简单看一下基本的使用方法。
一些基本注解和使用可以参照这篇文章。

//请求接口
public interface RequestService {
    @GET("path")//注解表明为get请求,值为相对url
    Call<DataModel> getData(@Query("key1") String value, @Query("key2") String value2);//请求的方法,参数代表一个一个的param配置(注解为key,值为value)
	//返回值Call为retrofit自带的返回值类型,下面会细说,返回值用于发起请求等后续工作
}
 
//构建retrofit对象,设置一些配置项
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://baseUrl/")//baseUrl
        .addConverterFactory(GsonConverterFactory.create())//设置请求参数和请求结果的数据转换,通常我们可以使用retrofit提供的Gson解析
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//设置返回类型的解析器,retrofit默认提供的是一个Call对象,可以直接发起请求,我们也可以使用其提供的RXJava的解析器,使其可以返回Observable对象进行链式调用请求,下面会细说
        .build();//builder模式构建

RequestService requestService = retrofit.create(RequestService.class);//通过retrofit的动态代理,创建请求接口对象
Call<DataModel> call = requestService.getData("v1","v2");//调用请求的代理对象的相应方法,传入参数,生成Call对象

call.enqueue(new Callback<DataModel>() {//使用Call对象enqueue发起异步请求,并设置回调
    @Override
    public void onResponse(Call<DataModel> call, Response<DataModel> response) {//请求成功
        DataModel model = response.body();
        //success
    }

    @Override
    public void onFailure(Call<BookSearchModel> call, Throwable t) {//请求失败
		//failed
    }
});
 
call.cancel();//取消掉请求:回调不会再调用,socket连接被终止

二.源码分析

1.Retrofit.Builder构建参数

创建请求需要一个Retrofit对象,我们也可以为每个请求有不同的配置,这个对象里面可以配置几个配置项,创建时使用的是builder模式

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

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {//CallFactory
      callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {//CallbackExecutor
      callbackExecutor = platform.defaultCallbackExecutor();
    }

    List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
    adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));//CallAdapterFactory

    List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);//ConverterFactory

    return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
        callbackExecutor, validateEagerly);//build
  }
}

由代码可知,创建retrofit对象使用的是builder模式,可以配置几个东西,baseUrl就是请求的基本url(在每个请求中也可配置整个url);其余的几个下面来单独说

2.可配置项

(1)CallFactory

CallFactory是请求所用的客户端,默认为OkHttpClient,我们也可以设置自己的OkHttpClient对象作为请求客户端

(2)ConverterFactory

请求的参数以及请求回来的数据,都需要转换,比如某个序列化和反序列化某个model,这就需要提供用于转换数据的东西,retrofit提供了ConverterFactory的类,通过工厂模式构建出Converter,提供将request和response转换的方法

public interface Converter<F, T> {
  T convert(F value) throws IOException;//F转换为T

  abstract class Factory {//工厂模式
	//提供将ResponseBody转换的Converter
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
	//提供将params转换为RequestBody的Converter
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }
  }
}
 
//retrofit提供的用gson转换的ConverterFactory
public final class GsonConverterFactory extends Converter.Factory {
  ...
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
  ...
}
//retrofit提供的用gson转换ResponseBody的Converter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  ...
  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
	return adapter.read(jsonReader);
  }
}

可以看到Gson的转换器就是使用Gson来解析数据的,同理我们可以实现自己的ConverterFactory构建不同的Converter,比如Jackson、fastjson等等

(3)CallAdapterFactory

刚刚我们说过,当我们调用一个接口的方法时,其返回值是用于发起请求等后续操作的Call对象,这是retrofit默认提供的一个包装了OkHttp请求的Call对象,可以方便的发起请求;

当我们想使用RXJava时怎么办?retrofit为我们提供了CallAdapterFactory,也是利用工厂模式生成CallAdapter对象,这个CallAdapter对象,就是用于将原始的OkHttpCall对象包装成我们想要的返回类型(retorfit使用的是okHttp,其创建的请求对象是OkHttpCall对象);

默认的,retrofit提供的是Call对象的CallAdapter:

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;//实际的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() {//回调结果
          @Override public void run() {
            if (delegate.isCanceled()) {
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }

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

由代码可知,默认的这个CallAdapter就是将原始的OkHttpCall对象包装到一个代理对象中返回了;

我们也可以引入retrofit提供的RXJava的CallAdapter,这个将在最后来讲,现在先不讲RXJava

(4)CallbackExecutor

当异步请求回来后,是处在工作线程中,那么如何在主线程的中回调callback呢?retrofit提供了Executor,用于以不同策略回调callback,默认提供就是回调的主线程的Executor了:

static class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());

  @Override public void execute(Runnable r) {
    handler.post(r);//回调到主线程中
  }
}

3.Retrofit.create动态代理生成请求对象

创建出retrofit对象后,需要用其构造出一个请求接口对象,才能进行后续的调用请求方法进行发送请求

使用retrofit的的create(Class)方法,会返回一个相应class类的请求接口对象:

public <T> T create(final Class<T> service) {
  ...
  //创建动态代理对象返回
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
      new InvocationHandler() {
        @Override public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
          ...
          ServiceMethod<Object, Object> serviceMethod =
              (ServiceMethod<Object, Object>) loadServiceMethod(method);//根据这个method对象,解析生成ServiceMethod对象,其保存请求方法解析出来的url、params等各种参数
          OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//构建OkHttpCall对象,保存serviceMethod和传入的参数,用户请求时生成完整的请求对象
          return serviceMethod.callAdapter.adapt(okHttpCall);//调用ServiceMethod中根据method的返回类型生成的CallAdapter的adapt方法,将OkHttpCall对象包装成相应类型返回
        }
      });
}

由代码可知,create方法使用了java的动态代理方法,构建出一个请求接口类型的代理对象返回,当我们调用接口对象某个请求方法时,就会代理到invoke方法中,参数包括了当前调用的方法method对象,以及调用时传入的各种参数args;

然后会根据method对象创建出ServiceMethod对象,这个对象后面会细说,他的作用就是解析method上的各种注解、参数类型、返回类型,并能根据这些生成相应的CallAdapter、Converter等等;

然后会构建一个OkHttpCall对象(内部会使用OkHttp真正发起请求),传入ServiceMethod对象和调用时的参数args,目的是当发起请求时,使用ServiceMethod解析出来的各种类型,结合相应的args生成完整的request对象,交由OkHttp发起请求;

最后调用ServiceMethod中,根据方法返回类型生成的CallAdapter的adapt方法,将这个原始的OkHttpCall对象包装成需要的类型返回,用这个对象即可完成后续的工作

4.ServiceMethod

上面说过在代理对象invoke方法里会调用loadServiceMethod方法,生成method对应的ServiceMethod对象,下面来看看具体的过程和其作用:

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();//否则通过builder模式创建一个ServiceMethod对象,并放入缓存
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

由代码可知,ServiceMethod的加载也是才去缓存方式,可以避免多次加载同一方法的对象,不过缓存cache不是静态变量,我们可以通过全局使用单例的retrofit来实现这一目的(实际上全局单例的retrofit就足够了,不用每次新建)

(1)创建

ServiceMethod的创建也是采用builder模式创建,传入retrofit和method对象:

//创建时拿到各种注解
Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();//方法上的注解
  this.parameterTypes = method.getGenericParameterTypes();//参数的类型
  this.parameterAnnotationsArray = method.getParameterAnnotations();//参数上的注解
}
 
//build构建
public ServiceMethod build() {
  callAdapter = createCallAdapter();//根据method的返回类型,去retrofit里注册的CallAdapter里依次去找,找到可以处理的CallAdapter即可
  responseType = callAdapter.responseType();//CallAdapter返回类型,这里指的其实是泛型类型,即Call时指的是实际请求的数据类型DataModel
  ...
  responseConverter = createResponseConverter();//根据responseType生成转换ResponseBody的Converter对象

  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);//根据方法签名上的注解,解析出相应的请求类型等值,如url、headers、请求方法、是否为富文本等信息
  }
  ...
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];//参数处理器,用于将注解等应用到实际参数上生成RequestBody
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];//第p个参数类型
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];//第p个参数的所有注解
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);//生成Handler
  }
  ...
  return new ServiceMethod<>(this);
}

根据返回类型,在retrofit里找到可以处理的CallAdapter和ResponseConverter,然后解析方法上的注解,保存下来,以及解析每个参数的注解,生成ParameterHandler对象用于后续处理实际参数,保存下来,构建ServiceMethod对象

(2)解析方法注解

方法注解

private void parseMethodAnnotation(Annotation annotation) {
  ...
  if (annotation instanceof GET) {//@GET注解
    parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
  }else if (annotation instanceof POST) {//@POST注解
    parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
  }else if (annotation instanceof Multipart) {//@Multipart注解
    ...
    isMultipart = true;//富文本编码格式
  }...
}
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
  ...
  this.httpMethod = httpMethod;//保存请求方法
  this.hasBody = hasBody;//是否有body
  ...
  this.relativeUrl = value;//relativeUrl
  this.relativeUrlParamNames = parsePathParameters(value);//url自带的参数,为了后边去重使用
}

根据在方法上注解的请求方法@GET,@POST,@HEADERS等解析出请求方法,headers等保存下来

(3)解析参数注解

参数注解

private ParameterHandler<?> parseParameterAnnotation(
    int p, Type type, Annotation[] annotations, Annotation annotation) {
  if (annotation instanceof Url) {//参数为完整url
    ...
    gotUrl = true;//完整url
	return new ParameterHandler.RelativeUrl();//处理该参数的相应的Handler对象
  } else if (annotation instanceof Query) {//为传递的键值对
    Query query = (Query) annotation;
    String name = query.value();
    boolean encoded = query.encoded();//是否需要编码

    Class<?> rawParameterType = Utils.getRawType(type);//获取参数的原始类型
    gotQuery = true;
	//根据参数原始类型决定处理的handler
	...
    if (rawParameterType.isArray()) {//比如参数类型是数组集合类型
      Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
      Converter<?, String> converter =
          retrofit.stringConverter(arrayComponentType, annotations);//需要一个将该类型转换为String的converter
      return new ParameterHandler.Query<>(name, converter, encoded).array();//使用converter构建处理Query的handler对象
    }...

  } else if (annotation instanceof Body) {//@Body参数
    ...
    Converter<?, RequestBody> converter;
    try {
      converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);//在retrofit中一次寻找能将type转换为RequestBody的converter对象
    }...
    gotBody = true;
    return new ParameterHandler.Body<>(converter);//使用converter构建处理Body的handler
  }
}

根据每个参数上的注解,比如@Query,@Body等,结合参数的类型,在retrofit中注册的converter中找到相应能处理的converter对象,包装到处理相应注解的ParameterHandler中,以便后续处理实际参数;

比如(@Body ParamModel model),就会生成ParameterHandler.Body<>对象,传入的converter应该是retrofit中注册的可以将ParamModel类型转换为RequestBody类型的Converter对象,后续调用时直接将实际参数model使用converter对象转换为RequestBody,作为body构建Request对象

至此,ServiceMethod对象构建完毕,保存了当前请求方法所有的已知参数、类型、方法、处理参数类等等东西,只等待发起请求时根据这些类结合实际参数构建出完整的Request对象即可

(4)请求时构建出完整的Request对象

Request toRequest(Object... args) throws IOException {
  RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
      contentType, hasBody, isFormEncoded, isMultipart);//使用已经解析出来的基本参数创建RequestBuilder对象
  ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
  int argumentCount = args != null ? args.length : 0;
  for (int p = 0; p < argumentCount; p++) {
    handlers[p].apply(requestBuilder, args[p]);//每个ParameterHandler对RequestBuilder应用arg参数
  }
  return requestBuilder.build();//构建Request对象,内部使用OkHttp的Request.Builder构建出Request对象
}
 
//比如处理@Body的ParameterHandler.Body
static final class Body<T> extends ParameterHandler<T> {
  private final Converter<T, RequestBody> converter;

  Body(Converter<T, RequestBody> converter) {
    this.converter = converter;
  }

  @Override void apply(RequestBuilder builder, T value) {
    RequestBody body;
	...
    body = converter.convert(value);//使用converter转换arg为相应类型
	...
    builder.setBody(body);//设置到RequestBuilder里
  }
}

(5)请求回来后将ResponseBody转换为结果类型

R toResponse(ResponseBody body) throws IOException {
  return responseConverter.convert(body);//使用创建时解析出来的ResponseConverter将ResponseBody转换为结果类型
}

5.OkHttpCall

生成ServiceMethod对象后,会创建一个OkHttpCall对象作为原始请求对象:

final class OkHttpCall<T> implements Call<T> {
  ...
  OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {//保存了ServiceMethod对象和实际参数args
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

  @Override public void enqueue(final Callback<T> callback) {//异步发起请求
    okhttp3.Call call;
    ...
	call = rawCall = createRawCall();//创建OkHttp的call对象
	...
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
		response = parseResponse(rawResponse);//转换response
        callSuccess(response);//回调callback
      }
	...
      private void callSuccess(Response<T> response) {
        callback.onResponse(OkHttpCall.this, response);//回调callback
      }
    });
  }

  private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);//这步是关键,使用serviceMethod结合(应用)args,生成完整的Request对象
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);//使用retrofit配置的CallFactory(OkHttpClient)执行request对象,生成OkHttp的call对象
    ...
    return call;
  }

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ...
    int code = rawResponse.code();
    if (code < 200 || code >= 300) {//请求成功/失败
      ...
    }
    ...
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);//包装responseBody
	...
    T body = serviceMethod.toResponse(catchingBody);//这步也是关键,使用ServiceMethod对象,将原始的ResponseBody转换为我们想要的(返回值泛型类型)类型数据
    return Response.success(body, rawResponse);
  }
}

OkHttpCall作为原始call对象,内部使用OkHttp进行实际的请求:

  1. 请求时使用ServiceMethod对象结合args实际参数,构建完整的Request对象(toRequest)

  2. 使用CallFactory,即OkHttpClient将request构建成OkHttp的Call对象

  3. 使用Call对象发起请求,监听回调

  4. 请求回来后,将ResponseBody使用ServiceMethod里解析出来的ResponseConverter对象,转换成结果类型(toResponse)

  5. 将结果回调到原始的callback中

6.CallAdapter包装返回类型

Retrofit.create的最后一步,就是将OkHttpCall对象使用CallAdapter的adapt方法,包装成想要的返回类型返回,我们来看看retrofit默认的实现:

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {//处理Call类型的返回值
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);//实际泛型类型
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);//返回一个代理对象
      }
    };
  }

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

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

    @Override public void enqueue(final Callback<T> callback) {
      delegate.enqueue(new Callback<T>() {//代理调用
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {//使用retrofit设置的CallbackExecutor,将结果回调到callback上
            @Override public void run() {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          ...
        }
      });
    }
  }
}

由代码可见,默认返回的这个CallAdapter,所提供的返回值就是一个代理了原始OkHttpCall对象的Call对象,其内部基本都是调用被代理对象;

当回调结果时,会使用retrofit里配置的CallbackExecutor进行回调,默认是MainThreadExecutor,将callback在主线程上回调

7.cancel

当我们想终止请求时,可以调用Call对象的cancel方法,原始的OkHttpCall对象会将cancel标志位置为true,也会将socket连接cancel掉,取消掉请求:

//OkHttpCall.cancel()
public void cancel() {
  canceled = true;//标志位置为true,请求还未发送时则不会发送了
  okhttp3.Call call;
  synchronized (this) {
    call = rawCall;
  }
  if (call != null) {
    call.cancel();//关闭OkHttp的call对象,包括socket连接
  }
}
 
//默认的代理类ExecutorCallbackCall.cancel
delegate.enqueue(new Callback<T>() {
  @Override public void onResponse(Call<T> call, final Response<T> response) {
    callbackExecutor.execute(new Runnable() {
      @Override public void run() {
        if (delegate.isCanceled()) {//如果已经被cancel掉则会模拟当作请求失败,调用onFailure,而不会调用onResponse
          callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
        } else {
          callback.onResponse(ExecutorCallbackCall.this, response);
        }
      }
    });
  }

  @Override public void onFailure(Call<T> call, final Throwable t) {
    ...
  }
});

由代码可知,cancel将不会发送还未发送的请求、已经发送的请求回调时回调onFailure(模拟一个IOException)而不是onResponse

这里应该注意,使用callback时,一般需要我们使用静态内部类+弱引用方式,一个是避免内存泄露,一个是防止比如界面销毁掉,还调用到了回调方法里(cancel掉也会执行到onFailure)使用一些界面相关的东西,会造成异常状况;也可以封装一层callback,在cancel的时候不会调用任何callback方法

三.结合RXJava

上面提到过我们可以将CallAdapter配置称retrofit提供的支持RXJava的CallAdapter,以便我们可以使用RXJava方式发起请求,下面我们来看看RXJavaCallAdapter是如何实现的

1.RXJavaCallAdapter

(1)RXJavaCallAdapterFactory

//CallAdapterFactory
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
  public static RxJavaCallAdapterFactory create() {//请求时使用当前线程发起请求,即调用call.execute
    return new RxJavaCallAdapterFactory(null, false);
  }
  public static RxJavaCallAdapterFactory createAsync() {//请求时使用异步发起请求,即调用call.enqueue
    return new RxJavaCallAdapterFactory(null, true);
  }
  public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {//请求时使用自定义的线程策略,即调用subscribeOn设置指定shcedulers
    return new RxJavaCallAdapterFactory(scheduler, false);
  }

  private final Scheduler scheduler;
  private final boolean isAsync;

  private RxJavaCallAdapterFactory(Scheduler scheduler, boolean isAsync) {
    this.scheduler = scheduler;
    this.isAsync = isAsync;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
	...
    if (rawType != Observable.class && !isSingle && !isCompletable) {//处理类型为Observable的返回值类型
      return null;
    }
    ...
    return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
        false);
  }
}

CallAdapterFactory的get方法,决定只处理返回值类型为Observable类型

创建factory时提供了是否异步等几个方式,构建RXJavaCallAdapter时会采用相应的方式,使其以不同线程策略发送请求

(2)RXJavaCallAdapter

//adapt方法包装OkHttpCall对象
@Override public Object adapt(Call<R> call) {
  //根据是否异步请求创建不同的OnSubscribe对象包装call
  OnSubscribe<Response<R>> callFunc = isAsync
      ? new CallEnqueueOnSubscribe<>(call)
      : new CallExecuteOnSubscribe<>(call);
  ...
  Observable<?> observable = Observable.create(func);//创建Observable对象
  //设置schedulers的话设置subscribeOn
  if (scheduler != null) {
    observable = observable.subscribeOn(scheduler);
  }
  ...
  return observable;
} 
 
//执行异步请求的CallEnqueueOnSubscribe
final class CallEnqueueOnSubscribe<T> implements OnSubscribe<Response<T>> {
  private final Call<T> originalCall;

  CallEnqueueOnSubscribe(Call<T> originalCall) {
    this.originalCall = originalCall;//原始call对象
  }

  @Override public void call(Subscriber<? super Response<T>> subscriber) {
    Call<T> call = originalCall.clone();
    ...
    call.enqueue(new Callback<T>() {//使用异步发起请求
      ...//回调subscriber
    });
  }
}

由代码可知,也就是根据是否异步等创建OnSubscribe对象,封装了原始call对象,并创建Observable对象返回,当subscribe开始执行时,会使用原始call对象进行请求,将结果通知到subscriber中即可

所以我们拿到的是一个Observable对象,可以进行后续操作了,在使用时还是要留意一下线程的切换是不是预想的

2.简单使用

下面来看下retrofit+RXJava的简单使用

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.createAsync())//异步请求方式
        .build();

final RXJavaService service = retrofit.create(RXJavaService.class);

service.getFirstData()//第一个请求
        .flatMap(new Func1<FirstModel, Observable<SecondModel>>() {
            @Override
            public Observable<SecondModel> call(FirstModel model) {
                return service.getSecondData(model);//继续发出第二个请求
            }
        })
        .observeOn(AndroidSchedulers.mainThread())//callback回调到主线程
        .subscribe(new Subscriber<SecondModel>() {
            @Override
            public void onCompleted() {
                //complete
            }

            @Override
            public void onError(Throwable e) {
                //error
            }

            @Override
            public void onNext(SecondModel model) {
                //success
            }
        });

你可能感兴趣的:(原理解析,android相关)