Android 深入Http(5)从Retrofit源码来看Http,真香警告

//Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.

Call repos = service.listRepos(“octocat”);

//或者

service.listRepos().enqueue(new Callback() {

@Override

public void onResponse(Call call, Response response) {

}

@Override

public void onFailure(Call call, Throwable t) {

}

});

可以看到,我们通过Call返回来的是一个ResponseBody,这个响应体还是没有解析完全,没有解析成一个JavaBean的。所以我们可以根据Retrofit支持Gson转换,在retrofit构建时添加下面代码:

.addConverterFactory(GsonConverterFactory.create(gson))

这样传回来的RespnseBody如果是个Json,那他就能转换成一个JavaBean。

我们就能把Api类的Call中的ResponseBody换成:

public interface GitHubService {

@GET(“users/{user}/repos”)

Call listRepos(@Path(“user”) String user);

}

这就体现了Retrofit对响应体处理的强大。

我们来读Retrofit源码结构吧。

Retrofit大致源码解析

==============================================================================

enqueue


我们以下面代码为例子:

api.getRepo().enqueue(new Callback<List>() {

@Override

public void onResponse(Call<List> call, Response<List> response) {

}

@Override

public void onFailure(Call<List> call, Throwable t) {

}

});

因为直接点进enqueue它是Call的抽象方法,而getRepo它也是个抽象方法,所以真正实现enqueue方法的应该是api对象里面的。

api又是由retrofit.create(Api.class)创建的,它创建了一个接口对象,所以我们去看create()方法,发现它终于是一个实现类了,也就是说这个方法它承接了后面所有的方法:

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, @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);

}

ServiceMethod<Object, Object> serviceMethod =

(ServiceMethod<Object, Object>) loadServiceMethod(method);

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

return serviceMethod.callAdapter.adapt(okHttpCall);

}

});

}

Create()是整个Retrofit的核心


这个方法它创建出了一个ApiService的实例。ApiService明明是一个接口,却能实现了其声明的所有的网络请求。

这说明这个方法是真的很顶,能把你这个接口类的所有网络请求方法整的明明白白。

我们来一行一行的分析:

第一段:

Utils.validateServiceInterface(service);

从方法名可以看出,这个方是做验证的:验证传进来的ApiService,是不是一个Interface类,我们点进去看一下:

static void validateServiceInterface(Class service) {

if (!service.isInterface()) {

throw new IllegalArgumentException(“API declarations must be interfaces.”);

}

if (service.getInterfaces().length > 0) {

throw new IllegalArgumentException(“API interfaces must not extend other interfaces.”);

}

}

是的,它首先会判断当前的类是不是一个Interface,其次它会判断当前的Interface有没有继承别的Interface,如果是的话就会抛出错误。

这个方法是做类型校验的,要求传进来的Interface类必须是原生的而且没有继承的。

第二段:

if (validateEagerly) {

eagerlyValidateMethods(service);

}

这也是一个验证,Eagerly是激进的意思,如果validateEagerly为true的话,Retrofiut会对ApiService做一个安全地、全面地验证,并且是在网络申请前做。这样的结果可能会导致程序卡一下, 而如果项目的Api很多,那我们在打开App的时候,它全都验证,那可能用户体验会极差。

所以我们一般都不会开这个玩意。

第三段

return (T) Proxy.new

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

ProxyInstance(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 {

}

});

看到了Proxy.newProxyInstance()和里面的invoke()方法,就是动态代理咯。

也就是可以认为在Retrofit中有一个代理类,专门帮我们配置这个Api信息。

至于动态代理,说到底就是 A对象有funcation()这个方法可以去获取一些东西,可是当前情况不能直接通过A来执行funcation方法,但是B对象可以做到,那我们通过给B对象设置 funcation()方法,让B去帮我们获取这些东西。而这个代理方法的入口正是invoke()

动态代理的本质是Java的反射机制,你要弄懂动态代理,必须要先弄懂Java的反射,而我之前已经浅析过Java的反射机制,里面正好讲到了动态代理的例子,非常好理解。

链接在这里:Java反射机制

这里我讲细一点,这里有两个类,一个是代理类,一个是被代理类

  • 被代理类

newProxyInstance()中传入的第一个参数service.getClassLoader(),获取service类的ClassLoader,这就说明service是被代理类,就是我们在retrofit.create(ApiService.class)的ApiService,它无法直接去执行网络请求,所以肯定有必要找代理类去帮我包装一下做事情。

  • 代理类

代理类是newProxyInstance()的最后一个参数,在这里就是new InvocationHandler() {...},它重写了invoke()invoke()就是实际的帮被代理类 去做网络请求的 方法,实际就是它来执行 listRepos()这个方法!!!!!!

到这里,我们就知道辽,整个return 返回的是一个动态代理类,当我们调用到网络请求的时候,这个动态代理类就会调用它的invoke方法。Ok那invoke方法里面具体是做什么的呢,我们来看一下。

invoke()方法


@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);

}

ServiceMethod<Object, Object> serviceMethod =

(ServiceMethod<Object, Object>) loadServiceMethod(method);

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

return serviceMethod.callAdapter.adapt(okHttpCall);

}

我们看下它的参数:

  • Object proxy:代理类

  • Method method:被代理的方法,比如ApiService的 listRepos()方法

  • Object[] args:这个method的参数

了解完后我们来看下下面的内容,也分为三段:

part1:

if (method.getDeclaringClass() == Object.class) {

//如果该方法是声明方法,则直接执行这个方法

return method.invoke(this, args);

}

什么是声明方法呢?比如 MainActivity的onStart()、onResume或者toString()、onBackPressed()这种要么已经在自己类里面声明,要么在父类里面就声明的方法,则它会直接调用这个方法。

也就是说,如果我们的 网络请求 它已经被某个类给声明并且实现而不是在interface中,那么Retrofit就会直接执行它。

就是一个验证方法而已。保证我们用的方法是在interface接口中的。

part2

if (platform.isDefaultMethod(method)) {

return platform.invokeDefaultMethod(method, service, proxy, args);

}

对不同的Java平台会做不同的行为。

所以这个也比较一般,不用去了解。

part3 重点

ServiceMethod<Object, Object> serviceMethod =

(ServiceMethod<Object, Object>) loadServiceMethod(method);

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

return serviceMethod.callAdapter.adapt(okHttpCall);

第一行用 loadServiceMehotd()来获取一个 ServiceMethod,来看看它做了什么:

// CallAdapter.java

ServiceMethod loadServiceMethod(Method method) {

ServiceMethod result;

synchronized (serviceMethodCache) {

result = serviceMethodCache.get(method); // 获取缓存 serviceMethodCache是一个 ConcurrentHashMap结构

if (result == null) {

result = new ServiceMethod.Builder(this, method).build(); // 如果没有缓存,就用build方法生成

serviceMethodCache.put(method, result);

}

}

return result;

}

上面方法中,如果获取不到缓存,就会去创建,所以使用Builder模式创建一个ServiceMethod对象,所以创建这一行比较关键:

// ServiceMethod.java

public Builder(Retrofit retrofit, Method method) {

this.retrofit = retrofit;

this.method = method;

this.methodAnnotations = method.getAnnotations(); // 方法注解

this.parameterTypes = method.getGenericParameterTypes(); //参数信息

this.parameterAnnotationsArray = method.getParameterAnnotations(); // 参数的注解

}

public ServiceMethod build() {

return new ServiceMethod<>(this);

}

build()中代码繁多,先不细究。不过从Builder中我们知道,ServiceMethod方法收集了我们Api Inteface中的所有方法的信息。

part3代码中,关于ServiceMethod一句话概括就是loadServiceMethod解析代入的method方法。

因为ServiceMethod具体做的是事情实在是太多了,根本就看不完,所以我们只挑几行看。反正只要知道他是用来解析Method的。

它做了很多很多事情,比如:

①:使用adapterFactory来对每个方法进行适配,一个网络请求方法就对应一个callAdapter

List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactojavaries);

adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

②:使用Executor来进行线程分配:

//主线程执行器

static class MainThreadExecutor implements Executor {

private final Handler handler = new Handler(Looper.getMainLooper());

@Override

public void execute(Runnable r) {

//就是使用Handler将结果返回到主线程

handler.post®;

}

}

③:将Method的注解进行解析并封装:

CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);

④:CallAdapte是由OkHttpClient实现的,所以这是为什么Retrofit低层是OkHttp

⑤:ServiceMethod可以走响应体的解析,将其从ResponseBody转换成具体的Javabean,通过Converter

part3中的第三行:

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

就是将解析后的方法填入到 OkHttpCall中,这个OkHttpCall是真正的Call对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值