retrofit2+rxjava+mockserver使用和理解
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了retrofit2+rxjava+mockserver使用和理解,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含13187字,纯文字阅读大概需要19分钟。
内容图文
特点概要
Square的retrofit作为目前android比较火的网络框架,具有以下特点:
1、rest api 风格
2、网络核心使用优秀开源框架okttp,其本身致力于组装request和便捷转换response。
3、代码简洁,拓展性高,开发包只有90k左右
4、支持RxJava、Guava、Java8等适配器。
简单使用
案例是一个简单的登陆请求案例。使用name和pwd参数登陆接口,返回获取response并直接转换成User对象,User有两个成员变量name,age。
使用步骤分解为:
1、创建retrofit
private
void
initRetrofit(){
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.56.1:12306/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
2、定义接口
public
interface
ApiServicce {
@FormUrlEncoded
@POST("/user/login/")
Call<User> login(@Field("name")String name, @Field("pwd")String pwd);
}
3、创建Call代理对象
ApiServicce apiService = retrofit.create(ApiServicce.class);
Call<User> userCall = apiService.login("name","retrofit");
4、发起请求并获取回调内容
@Override
public
void
onResponse(Call<User> call, Response<User> response) {
User user = response.body();
}
@OverridepublicvoidonFailure(Call<User> call, Throwable t) {
System.err.println(call.toString());
}
});
以上四个步骤就完成了一个完成的数据请求和回复的解析。高度解耦的特点只能用简洁优雅来形容。那么他怎么做到的呢我们稍后分析。这里涉及到一个的接口是使用mockserver来模拟完成的,有关于mockserver的工作可以从github mockserver了解。这里我使用的是简易的moco,只需要是简单使用其jar包和定义一个配置便可以轻松的完成一次模拟过程。详情可以参考这里。
服务启动命令:
java -jar moco-runner-0.11.0-standalone.jar http -p 12306 -c foo.json
foo.json内容:
[
{
"request" :
{
"uri" :"/user/login/",
"method" :"post"},
"response" :
{
"json" :
{
"name" : "jerry",
"age" :"24"}
}
},
{
"request":
{
"uri" : "/"},
"response" :
{
"text" : "hello"}
}
]
可以看出调用
http://192.168.56.1:12306/返回hello的文本内容,调用http://192.168.56.1:12306/user/login 返回上述的json串再经由retrofit转换成对应的java对象。ok,大体了解了使用方法,开始剖析他的工作原理。
原理剖析
可以看出其工作流程主要分为下面四步
下面对其源码进行分析:
结合我们使用过程 retrofit build
retrofit build
public Retrofit build() {
if (baseUrl == null) {
thrownew 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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
returnnew Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
实例CallFactory,CallFactory决定调用的网络模块使用的是哪个,这里默认使用的是OkHttpClient。成员callbackExecutor为执行回调的任务或线程。成员adapterFactories存放CallAdapter的一个列表,并且add一个默认的AdapterFactory,AdapterFactory中get方法用来获取到指定的CallAdapter。先来看下默认的AdapterFactory是什么,位置ExecutorCallAdapterFactory类。
CallAdapter
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
returnnull;
}
final Type responseType = Utils.getCallResponseType(returnType);
returnnew CallAdapter<Call<?>>() {
@Overridepublic Type responseType() {
return responseType;
}
@Overridepublic <R> Call<R> adapt(Call<R> call) {
returnnew ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
return new ExecutorCallbackCall,那么看下这个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;
}
@Overridepublicvoidenqueue(final Callback<T> callback) {
if (callback == null) thrownew NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@OverridepublicvoidonResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Overridepublicvoidrun() {
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);
}
}
});
}
@OverridepublicvoidonFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Overridepublicvoidrun() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
@OverridepublicbooleanisExecuted() {
return delegate.isExecuted();
}
@Overridepublic Response<T> execute() throws IOException {
return delegate.execute();
}
@Overridepublicvoidcancel() {
delegate.cancel();
}
@OverridepublicbooleanisCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.@Overridepublic Call<T> clone() {
returnnew ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Overridepublic Request request() {
return delegate.request();
}
}
ok,很简单。只是一个Call的代理类,不了解Call对象的可以去研究下okhttp。delegate.enqueue回复之后使用callbackExecutor将回复处理放回到一个子线程交由callback处理。做好这些准备工作之后。需要看下他是如果做到create代理对象的解耦和连接整个的工作流程。
retrofit create
retrofit.create(申明的接口class)
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() {
privatefinal Platform platform = Platform.get();
@Overridepublic Object invoke(Object proxy, Method method, 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 = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
可以看出这里使用了一个动态代理来代理service类,观察其InvocationHandler代理改变的部分,其Object的方法都自动被原样的执行,当调用service里面的请求方法的时候会被Proxy拦截,loadServiceMethod方法讲原方法包装成ServiceMethod,ServiceMethod类主要工作是解析注解、传参,将他们分装成request,然后再根据具体的返回值,将之前配置的工场Factory生成具体的CallAdapter和ResponseConvert。 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args)。显式的实例了一个OkhttpCall对象,OkHttpCall封装了Call(okhttp中的对象),说明retrofit是使用了okttp最为网络的核心模块。最后一步serviceMethod.callAdapter.adapt(okHttpCall),callAdater是用来做什么的呢,其本质是将call转成一个T型的策略。下面先对CallAdapter如何工作的进行剖析,并且如何整合Rxjava来使用的。
结合Rxjava
如果我们想使用Rxjava 那么接口方法定义得是这样的
@FormUrlEncoded
@POST
Observable<User> rxLogin(@Field("name")String name, @Field("pwd")String pwd);
那么如何才能转换成我们想要的Observable类型呢,前面我们说过CallAdapter旨在转换Call成为我们想要的T类型。那么需要在CallAdapter上做文章了。重点看下RxJavaCallAdapterFactory类
public
final
class
RxJavaCallAdapterFactory
implements
CallAdapter.Factory
CallAdapter.Factory是Retrofit这个库中的接口,用来给我们自定义去解析我们自己想要的类型用的。
get方法获取CallAdapter的方法
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = Utils.getRawType(returnType);
boolean isSingle = "rx.Single".equals(rawType.getCanonicalName());
if (rawType != Observable.class && !isSingle) {
returnnull;
}
if (!(returnType instanceof ParameterizedType)) {
String name = isSingle ? "Single" : "Observable";
thrownew IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType);
if (isSingle) {
// Add Single-converter wrapper from a separate class. This defers classloading such that// regular Observable operation can be leveraged without relying on this unstable RxJava API.return SingleHelper.makeSingle(callAdapter);
}
return callAdapter;
}
如果不是Observable的类型,则不去处理.Observable类型则调用callAdapter()方法获取对应的CallAdapter。callAdapter()方法中return SimpleCallAdapter的实例,那么观察SimpleCallAdapter的实现
static
final class SimpleCallAdapter implements CallAdapter<Observable<?>> {
privatefinal Type responseType;
privatefinal Scheduler scheduler;
SimpleCallAdapter(Type responseType, Scheduler scheduler) {
this.responseType = responseType;
this.scheduler = scheduler;
}
@Overridepublic Type responseType() {
return responseType;
}
@Overridepublic <R> Observable<R> adapt(Call<R> call) {
Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
.lift(OperatorMapResponseToBodyOrError.<R>instance());
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
}
好了,最终我们看到了adapter返回类型就是Observeble了。再回顾下retrofit create的过程中我们代理proxy return的结果是serviceMethod.callAdapter.apater(call)那么我们取得的是不是就一个Observerble对象了!!!那么create拿到的代理对象就是一个observable对象。就可以轻松的使用Rxjava了!!!如果不了解rxjava的可以了解下github rxjava
Request and Response
retrofit的重点是是组装request和回复response类型的转换。serviceMethod类是用来根据注解组装请求参数的。serviceMethod的build方法
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.");
}
returnnew ServiceMethod<>(this);
}
createCallAdapter创建对应的callAdapter,即从CallAdapterFactory中取出需要的适配器,responseConverter创建对应的回复处理类,从List
@Override
public
void
enqueue(final Callback<T> callback) {
if (callback == null) thrownew NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) thrownew IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@OverridepublicvoidonResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@OverridepublicvoidonFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
privatevoidcallFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
privatevoidcallSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
使用okttp的call对象拿到回复之后调用parseResponse获得到指定的response对象。最终是调用serviceMethod中的toResponse进行转换成对应的T类型。
/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
所以这里就是使用了我们指定的responseConverter进行转换。如GsonConverterFactory。转换的方式根据不同Converter来定,不做详述。由此可见,通过ServiceMethod的协调完成了request的组装和response回复的转换。
原文:http://blog.csdn.net/tangjiean/article/details/51721356
内容总结
以上是互联网集市为您收集整理的retrofit2+rxjava+mockserver使用和理解全部内容,希望文章能够帮你解决retrofit2+rxjava+mockserver使用和理解所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。