Retrofit源码学习记录
1. Retrofit的创建过程
当我们使用Retrofit请求网络时,首先写请求接口
public interface IpService {
@GET("getIpInfo.php?ip=59.108.54.37")
Call<IpModel> getIpMsg();
}
接着,我们调用如下代码来创建Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
Retrofit是通过建造者模式构建出来的,我们看看第一行Builder()方法做了什么
Builder()方法
public Builder() {
this(Platform.get());
}
很简短,跟进get()方法
get()方法
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
一个静态的get()方法里返回的是PLATFORM,而PLATFORM又是由findPlatform()方法创建的,用处是根据不同运行平台提供不同的线程池
接下来看看创建Retrofit时调用的build()方法
build()方法
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
第1个if语句块中很明显,baseUrl是必须指定的,不然会抛异常
第2个if语句块中的callFactory默认为this.Factory。这个就是我们在构建Retrofit时调用callFactory()方法传进来的,如下所示
callFactory()方法
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
因此,如果需要对OkHttpClient进行设置,则可以构建OkHttpClient对象,然后调用callFactory()方法将设置好的OkHttpClient传进去
再回到上面的build()方法,接着说第2个if语句块,发现如果callFactory为null,就直接创建OkHttpClient
第3个if语句块中的callbackExecutor用来将回调传递到UI线程
第1个List<>集合对象callAdapterFactories主要用于存储对Call进行转化的对象
第2个List<>集合对象converterFactories主要用于存储转化数据对象,此前在创建Retrofit时我们调用的addConverterFactory(GsonConverterFactory.create())就是设置返回的数据支持转换为Gson对象,最终会返回配置好的Retrofit类
2. Call的创建过程
我们创建Retrofit实例并调用如下代码的来生成接口的动态代理对象
IpService ipService = retrofit.create(IpService.class);
我们来看看create()方法做了什么
create()方法
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();
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) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
create()方法在第1个return处返回了一个Proxy.newProxyInstance动态代理对象。当我们调用IpService的getIpMsg()方法时,最终会调用InvocationHandler的invoke()方法,它有三个参数,第一个是代理对象,第二个是调用方法,第三个是方法参数。最后的loadServiceMethod(method)中的method就是我们定义的getIpMsg()方法,下面我们看看loadServiceMethod()方法做了什么
loadServiceMethod()方法
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
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;
}
从serviceMethodCache查询传入的method是否有缓存,如果有,就用缓存。如果没有,就创建一个,并加入serviceMethodCache缓存起来,下面看看ServiceMethod是如何构建的
ServiceMethod的parseAnnotations()方法
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
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.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract T invoke(Object[] args);
}
ServiceMethod是一个抽象类,返回的是它子类HttpServiceMethod的parseAnnotations()方法,如下
HttpServiceMethod的parseAnnotations()方法
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/**
* Inspects the annotations on an interface method to construct a reusable service method that
* speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
* method only once and reuse it.
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
在该方法中直接new HttpServiceMethod对象
HttpServiceMethod()方法
private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
CallAdapter<ResponseT, ReturnT> callAdapter,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}
这里就是一个构造器,有一些属性
回到ServiceMethod的parseAnnotations()方法,我们发现callAdapter对象调用了createCallAdapter()方法,跟进看看里头做了什么
createCallAdapter()方法
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
最后返回的是retroft.callAdapter()方法,继续跟进
callAdapter()方法
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
返回nextCallAdapter()方法
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;
}
}
在第一个for循环里,还记得callAdapterFactories吗,adapter对象就是Retrofit的build()方法里(如下)的callAdapterFactories对象调用get()方法添加的
build()方法
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
callAdapterFactories列表默认添加defaultCallAdapterFactory(),他指的是ExecutorCallAdapterFactory
defaultCallAdapterFactory()方法
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return singletonList(new ExecutorCallAdapterFactory(callbackExecutor));
}
return singletonList(DefaultCallAdapterFactory.INSTANCE);
}
ExecutorCallAdapterFactory的get()方法如下
get()方法
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
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);
}
};
}
get()方法会得到CallAdapter对象,它的responseType会返回数据的真实类型,比如传入的Call<IpMOdell>,responseType()方法就会返回IpModel。最后的adapt()方法会创建ExecutorCallbackCall,将call的回调转发至UI线程
回到上面ServiceMethod的parseAnnotations()方法,调用createResponseConverter()方法创建responseConverter对象
ServiceMethod的parseAnnotations()方法
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
我们看看这个方法做了什么
createResponseConverter()方法
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
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.responseBodyConverter()方法,点进去看
responseBodyConverter()方法
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
继续跟进nextResponseBodyConverter()方法
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;
}
}
原来在这里遍历converterFactories列表存储的Converter.Factory,返回一个合适的converter用来转换对象。
此前我们在创建Retrofit时调用addConverterFactory(GsonConverterFactory.create()),这段代码将GsonConverterFactory添加到converterFactories列表中,表示返回的数据类型支持转换为JSON对象。
再次回到ServiceMethod类,查看这一行代码
ServiceMethod
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
观察RequestFactory的parseAnnotations()方法
RequestFactory的parseAnnotations()方法
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
查看返回的build()方法
RequestFactory的build()方法
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...
不多截取,看看parseMethodAnnotation()方法
parseMethodAnnotation()方法
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;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
可以看到就是上一篇文章里我们学习过的HTTP请求注解,原来这个方法是用来解析地址和请求方式的
再回头去看看ExecutorCallAdapterFactory的adapt()方法,它创建了ExecutorCallbackCall,ExecutorCallbackCall部分代码如下
ExecutorCallbackCall
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
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()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
可以看出这里就是ExecutorCallbackCall对Call的封装,主要通过callbackExecutor将请求回调到UI线程。我们在使用Retrofit时,得到Call对象后会调用它的enqueue()方法,其实调用的是ExecutorCallbackCall的enqueue()方法,从上面代码也可以看出最终调用的时delegate的enqueue()方法,而delegate就是传入的OkHttpCall
OkHttpCall的enqueue()方法
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
...
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
...
截取部分,我们看看比较重要的parseResponse()方法
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);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(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;
}
}
这个方法比较明显的是通过状态码code来执行操作,如果顺利,会调用responseConverter.convert()方法
convert()方法
@Nullable T convert(F value) throws IOException;
跟进如下
OptionalConverterFactory的convert()方法
@Override public Optional<T> convert(ResponseBody value) throws IOException {
return Optional.ofNullable(delegate.convert(value));
}
其实这里就是上文我们看的createResponseConverter方法返回的Converter了,因为由上文的方法跟进也是到这里结束,此前例子中我们用的是Gson,因此我们查看GsonConverterFactory里的代码是如何返回Converter的
GsonConverterFactory的responseBodyConverter()方法
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
返回GsonResponseBodyConverter,跟进
GsonResponseBodyConverter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
在中间的构造器里,最终,创建GsonResponseBodyConverter,并在下面的convert()方法里将回调数据转为JSON格式。Call的enqueue主要做的就是用OkHttp来请求网络,将返回的Response进行数据转换并回调给UI线程
Retrofit源码分析到此结束
我们简单串联一下用到的方法:
Retrofit的创建:
Builder()——get()——build()——callFactory()
Call的创建:
create()——loadServiceMethod()——ServiceMethod的parseAnnotations()——HttpServiceMethod的parseAnnotations()——HttpServiceMethod()
添加adapter对象:
ServiceMethod的parseAnnotations()——createCallAdapter()——callAdapter()——nextCallAdapter()——defaultCallAdapterFactory()——ExecutorCallAdapterFactory的get()
创建转换类型对象:
ServiceMethod的parseAnnotations()——createResponseConverter()——responseBodyConverter()——nextResponseBodyConverter()
解析请求和地址:
ServiceMethod的parseAnnotations()——RequestFactory的parseAnnotations()——RequestFactory的build()——parseMethodAnnotation()
回调和封装:
ExecutorCallAdapterFactory的adapt()——ExecutorCallbackCall类——OkHttpCall的enqueue()——parseResponse()——convert()
总结一下核心思想
Retrofit总的来说是对OkHttp的一层封装,先通过建造者模式构造Retrofit对象,在其build方法中创建了Retrofit的两个核心,即CallAdapter和Converter。前者用于适配返回的数据类型,配合RxJava时就可以返回Observable。后者就是转换器,主要负责把服务器返回的数据ResponseBody转化为 T 类型的对象
然后进入到Retrofit的设计思想里——动态代理,通过create方法创建接口代理对象实例,这个方法里做了一些判断,会根据不同条件选择进入正常流程invoke里或者loadServiceMethod.invoke
先简单介绍一下loadServiceMethod,这个方法它主要是将网络请求方法中的信息比如注解和参数,进行初步的处理。解析接口后又生成了一个RequestFactory请求工厂对象,并且利用这个RequestFactory对象创建了一个CallAdapter。invoke方法里则通过RequestFactory生成一个OkHttpCall对象,然后调用adapt方法,由内部的CallAdapted调用,而这个CallAdapted就是Retrofit动态代理创建的最核心的产物
CallAdapted是adapt方法的实现类,里面的变量callAdapter调用了一个同名adapt方法,存在于CallAdapter接口中。CallAdapter是根据returnType和annotations的类型,从callAdapterFactories工厂中进行查找,从而返回所对应的网络请求适配器。那么既然有查找,反过来寻找添加,添加在一开始的build方法里。添加调用适配器工厂的目的就是支持Call以外的服务方法返回类型,如支持Observable返回类型等(同理于Converter数据转换器)。在callAdapterFactories集合器添加一个默认适配器工厂时,也附带传进去了一个参数callbackExecutor,callbackExecutor是Java8或者Android平台的一个默认线程调度器,它的作用就是通过Handler把网络请求的后台线程切回到主线程。完成从网络请求到完成线程切换的过程
所以为什么Retrofit要使用动态代理呢?动态代理的优势是不用暴露真实的委托者,根据不同的委托创建不同的代理,通过代理去做事情。另外,封装OkHttp使得Retrofit弥补了其缺点,如繁琐的请求参数的配置。利用@GET、@POST、@Path、@Body等注解以及一些参数很简便的就构造出了请求。当Retrofit创建了不同的接口,动态代理就发挥出了作用。每当不同接口方法执行时,动态代理都会拦截该请求,对接口中的注解,参数进行解析,构建出不同的Request,最后则交给OkHttp去真正执行。Retrofit结合动态代理,不用关心真正的接口方法,对符合规范的接口进行统一化的管理,以统一的方式解析注解和参数,拼接成request
说了这么多,Retrofit的核心工作流程就是
- 动态代理中调用loadServiceMethod方法,解析接口方法中的注解,参数,头部信息等
- 依据接口方法的返回类型,从适配器工厂集合里进行查询,生成相应的适配器CallAdapter,区分是RxJava的Observable、Single还是Call或者其他类型,(适配器工厂集合的数据是由构建Retrofit时addCallAdapterFactory()添加,如无自定义,则添加Android平台默认适配器)。以相同的方式取出数据转换器Converter
- 利用上面生成的CallAdapter,调用invoke方法,创建OkHttpCall对象,即针对请求信息,利用OkHttp进行异步或者同步网络请求,并且对响应结果进行实体类转换
- 创建好OkHttpCall后,又利用上面查询到的适配器CallAdapter调用adapt,返回RxJava的Observable、Single或者Call对象。最后将线程从后台切换为主线程
本文摘抄自《Android进阶之光——刘望舒》,为自己学习路程中的记录,不以盈利为目的。
欢迎指正。