系列文章推荐:
Android 必须知道的网络请求框架库,你不可错过的框架介绍篇
Android Retrofit 2.0(一)初次见面请多多关照
Android Retrofit 2.0(二)使用教程OkHttp3 + Gson + RxJava
private void getLogin() {
Retrofit retrofit = new Retrofit.Builder() //1、创建Retrofit对象指定域名
.baseUrl("http://localhost:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiManager apiService = retrofit.create(ApiManager.class); //2、对象创建一个API接口对象:
Call call = apiService.getData("lyk", "1234");
call.enqueue(new Callback() { //3、call对象发生同步/异步请求
@Override
public void onResponse(Call call, Response response) {
if (response.isSuccess()) {
// 请求成功
} else {
//直接操作UI 或弹框提示请求失败
}
}
@Override
public void onFailure(Call call, Throwable t) {
//错误处理代码
}
});
}
ApiManager接口
public interface ApiManager {
//根据api新建一个Java接口,用Java注解来描述这个api
@GET("login/")
Call getData(@Query("name") String name, @Query("password") String pw);
Java动态代理,是一种结构性设计模式,可以在要调用的Class方法前或后,插入想要执行的代码进行改造。例如猪八戒娶媳妇,剧情中娶的媳妇并非高翠兰本人,而是一个代理人,即孙悟空。
案例中关键两行代码:
ApiManager apiService = retrofit.create(ApiManager.class); //2、retrofit对象创建一个API接口对象
Call call = apiService.getData("lyk", "1234"); //返回响应接口回调
这简短的两行代码,隐藏了Request请求体并拿到Response返回Call对象。跟着好奇心去打开源码一探究竟吧!进入 create 方法一看发现代码很少,但这几行代码才是 Retrofit 精妙之处。
/** Create an implementation of the API defined by the {@code service} interface. */
public T create(final Class 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, 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);
}
});
}
源码分析:
案例中 Retrofit 创建了一个 apiService 对象的实例 ,其实是得到的 apiService 是一个动态代理对象,并不是 APIManger 本尊实例化对象(哈哈~高翠兰是孙悟空变的!)而当 apiService 对象调用 getData方法时,就会被这个动态代理拦截并在内部做些小动作,它会调用 Proxy.newProxyInstance方法 中的 InvocationHandler 对象,它的 invoke方法 会传入3个参数:
Retrofit 得到了 method 和 参数args 。接下去 Retrofit 就会用 Java反射 获取到 getData方法 的注解信息,配合args参数,创建一个ServiceMethod对象。关键就在于 ServiceMethod 对象,Retrofit 费心费力就为了创建它到底是想做什么呢?
ServiceMethod 是服务于请求方法的,服务于传入Retrofit的proxy对象的method方法,即getData方法。如何服务呢?它可以将method通过各种内部接口解析器进行组装拼凑,最终生成一个Request请求体。这个Request 包含 api域名、path、http请求方法、请求头、是否有body、是否是multipart等等。最后返回一个Call对象,Retrofit2中Call接口的默认实现是OkHttpCall,它默认使用OkHttp3作为底层http请求client。一句话就是:Retrofit 使用Java动态代理就是要拦截被调用的Java方法,然后解析这个Java方法的注解,最后生成Request由OkHttp发送Http请求。
想要弄清楚Retrofit的细节,先来简单了解一下Retrofit源码组成结构:
void onResponse(Response response);
void onFailure(Throwable t);
ApiManager apiService = retrofit.create(ApiManager.class); //2、retrofit对象创建一个API接口对象
Call call = apiService.getData("lyk", "1234"); //返回响应接口回调
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
responseConverter = createResponseConverter();
然后,解析Method方法的注解,其实就是想获取Http请求的方法。比如请求方法是GET还是POST形式,如果没有程序就会报错。还会做一系列的检查,比如在方法上注解了@Multipart,但是Http请求方法是GET,同样也会报错。
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
其次,比如上面 apiService 接口的方法中带有参数{name,password},这都占位符,而参数值是在Java方法调用中传入的。
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
最后,ServiceMethod 还会做其他的检查。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(ProtoConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
上面代码创建了一个Retrofit对象,支持Proto和Gson两种数据格式,并且还支持RxJava。
参考连接:
https://blog.csdn.net/jiankeufo/article/details/73186929