作者:chaozhouzhang
一、使用
1、创建HTTP接口
首先创建HTTP的API服务接口,接口下的一个方法对应HTTP的一个请求,方法上面的注解表示请求的接口地址部分,返回类型是请求的返回值类型,方法的注解参数即是请求的参数。
public interface ApiService {
/**
* 登录:
* 账号+密码
*
* @param body
* @return
*/
@POST("/ny/consumer/login")
Observable<BaseResponse<User>> login(@Body RequestBody body);
}
2、构建Retrofit实例
配置OkHttpClient实例; 设置HTTP接口的域名地址; 添加RxJava2网络请求适配器工厂; 添加Gson数据转换器工厂;
sRetrofit = new Retrofit.Builder()
.client(sOkHttpClient)
.baseUrl(HOST)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
3、生成ApiService的动态代理
通过Retrofit生成动态代理,用于发起HTTP请求。
sApiService = sRetrofit.create(ApiService.class);
4、发起请求 使用动态代理发起HTTP请求。
getApiService().login(requestBody);
二、解析
2.1、Retrofit实例的构建
Retrofit实例的构建使用建造者模式,包括
1、okhttp3.Call.Factory
也就是OkHttpClient,因为OkHttpClient实现了okhttp3.Call.Factory,用于发起请求。
2、Executor
用于提交回调任务,默认使用Platform.Android的MainThreadExecutor,其实现了Executor接口,并在执行回调中实现了主线程Handler的handler.post(runnable)操作,用于将异步请求的回调结果从子线程切换到主线程。
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
3、List<CallAdapter.Factory>
网络请求适配器工厂,默认使用Platform.Android的ExecutorCallAdapterFactory,该网络请求适配器工厂适配的网络请求是ExecutorCallbackCall。
@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);
}
};
}
4、List<Converter.Factory>
数据转换器工厂,默认使用的是Platform.Android的OptionalConverterFactory,该数据转换器工厂使用的是默认的OptionalConverter。
2.2、生成ApiService的动态代理并发起HTTP请求
采用动态代理可以非常灵活地实现解耦,传入ApiService的Class对象,Proxy提供了用于创建动态代理对象的静态方法,执行动态代理实例的每个方法时都会被替换为执行InvocationHandler对象的invoke方法。
public <T> T create(final Class<T> service){}
InvocationHandler对象的invoke方法中最后调用的是ServiceMethod的invoke方法:
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
也就是HttpServiceMethod实现的invoke方法: 方法中进行了网络请求适配器对OkHttpCall进行的适配,也就是说网络请求是使用OkHttpCall进行的,但返回类型由网络请求适配器进行适配。
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
从上文配置请求网络适配器工厂我们知道,默认的网络请求适配器适配的是ExecutorCallbackCall,故默认使用ExecutorCallbackCall的enqueue做异步网络请求:
@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);
}
});
}
});
}
这里的delegate就是OkHttpCall实例,callbackExecutor就是MainThreadExecutor实例,OkHttpCall异步请求回调后,使用MainThreadExecutor提交回调任务,该任务执行的就是在异步请求回调的子线程中将异步请求的回调结果从子线程切换到主线程。
其中OkHttpCall的异步请求方法中,调用的就是okhttp3.Call的异步请求,回调结果中会使用Converter<ResponseBody, T>对数据进行转换并返回。
T body = responseConverter.convert(catchingBody);
2.3、RxJava网络请求适配器工厂
使用RxJava2CallAdapter做网络请求适配器,将Call转换为Observable<Response>。
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
2.4、Gson数据转换器工厂
使用GsonResponseBodyConverter做数据转换器,将ResponseBody转换为T。
@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();
}
}
三、总结
首先,服务接口配置了对应HTTP请求的方法,并以注解的方式配置了请求地址和参数。
第二,创建Retrofit实例,实例配置了接口域名地址、OkHttpClient客户端、Executor执行器、网络请求适配器工厂、数据转换器工厂,其中OkHttpClient客户端用于执行网络请求操作、Executor执行器用于执行将异步请求结果从子线程切换到主线程的回调任务、网络请求适配器工厂用于适配接口方法返回值的类型,数据转换器工厂用于转换返回数据类型。
第三,使用Retrofit实例生成HTTP服务接口的动态代理实例,当动态代理实例进行请求方法执行的时候,将会执行InvocationHandler实例的invoke方法,其实就是执行具体的网络请求适配器工厂适配OkHttpCall的方法,该方法中会进行OkHttpCall封装的okhttp3.Call的enqueue异步网络请求,请求结束后会对请求响应数据使用具体的数据转换器工厂进行转换并返回,最后使用执行器利用Handler的post(Runnable)进行线程切换后回调响应。
最后贴一下Stay的流程图:
在这里我也分享一份可以帮助提高自己的能力,提升竞争力的资料,我平常一直会专研的Android学习PDF+架构视频+源码笔记,高级架构技术进阶脑图、高级进阶架构资料
如果你有需要的话,可以找我获取, 【加入】资源丰富,学习氛围浓厚的圈一起学习交流吧!
喜欢本文的话,不妨顺手给我点个小赞、评论区留言或者转发支持一下呗~
网友评论