Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
.build();
RetrofitService service = retrofit.create(RetrofitService.class);
Observable observable = service.getPostInfoRx("yuantong", "11111111111");
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(PostInfo postInfo) {
Log.i("http返回:", postInfo.toString() + "");
}
});
问题有三个:
为什么只是写接口Service就可以实现网络请求, 这个逻辑是怎样的?
返回对象是怎么转成Observable的?
返回对象ResponseBody怎么通过Gson转成泛型对象的?
源码梳理
Retrofit
Retrofit#create
public T create(final Class service) {
//检查service是否是接口类型, 并且service不允许继承其它接口
Utils.validateServiceInterface(service);
//是否提前加载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, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
//如果调用的是Object中的方法, 则直接调用该方法
return method.invoke(this, args);
}
//是否是平台的默认方法
//Platform是接口, 有Android和Java8两个实现类
//上面的Platform.get()方法会判断当前的系统类型
//之所以这么处理, 是因为像Java8那样, 接口中是支持默认方法的
//如果是默认方法, 就直接调用
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//加载方法信息(方法参数/返回值类型/注解信息等)
ServiceMethod
这里重点就是最后的三行方法.
Retrofit#loadServiceMethod
//动态代理前面执行的这个方法
//遍历service中的全部public方法执行loadServiceMethod
private void eagerlyValidateMethods(Class> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
//serviceMethodCache缓存信息
ServiceMethod, ?> loadServiceMethod(Method method) {
//serviceMethodCache的类型是Map>
//如果已经加载过, 就从serviceMethodCache取出直接返回
//这也就是执行eagerlyValidateMethods的意义
//提前加载
ServiceMethod, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
//保证线程按全
//这里是不是很像单例里的双检锁/双重校验锁(DCL)
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//如果没加载过, 就创建ServiceMethod
//ServiceMethod这里就是保存方法的各个信息
result = new ServiceMethod.Builder<>(this, method).build();
//缓存进serviceMethodCache
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod
ServiceMethod.Builder<>(this, method).build()
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取方法的注解信息, 注解可以有多个, 所以是数组
//比如注解@Get @NotNull
this.methodAnnotations = method.getAnnotations();
//方法的参数类型
this.parameterTypes = method.getGenericParameterTypes();
//方法的参数中的注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
//获取callAdapter
//注意这个方法, 该方法和问题2有关
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?");
}
//注意这个方法, 该方法和问题3有关
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//...各种检查
//Builder模式
//最终生成ServiceMethod, 将builder中的各个参数保存到ServiceMethod中
return new ServiceMethod<>(this);
}
private CallAdapter createCallAdapter() {
//拿到方法的返回值信息
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
//最终, 我们的callAdapter是在retrofit类中获取
return (CallAdapter) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
Retrofit#callAdapter
public CallAdapter, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
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;
//遍历callAdapterFactories, 一个一个去找
//找到就返回
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//...
//如果没找到, 输出异常信息
}
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
//...
//解析返回结果
//这里也是问题3的关键
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//解析结果
//泛型解析
//这里跟我们创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)对应
T body = serviceMethod.toResponse(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;
}
}
动态代理代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。比如,现在存在一个UserService类:public class UserService { public void test() { System.out.println("test..."); }}此时,我们new一个UserService对象,然后执行test()方法,结果是
public class OcuppyMoreThanHalf {
/**
* Q74 数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字
* two solutions:
* 1.O(n)
* see <beauty of coding>--每次删除两个不同的数字,不改变数组的特性
* 2.O(nlogn)
* 排序。中间
cygwin很多命令显示command not found的解决办法
修改cygwin.BAT文件如下
@echo off
D:
set CYGWIN=tty notitle glob
set PATH=%PATH%;d:\cygwin\bin;d:\cygwin\sbin;d:\cygwin\usr\bin;d:\cygwin\usr\sbin;d:\cygwin\us