当前位置: 首页 > news >正文

深圳哪做网站/谷歌chrome手机版

深圳哪做网站,谷歌chrome手机版,官网网站系统,如何做公司网页制作Retrofit源码角度来Http 前言 本篇Blog是Android深入Http的最后一篇。 也是是说写完本篇blog,我在Android关于Http的方面已经有了足够的开发基础了,以后至少见到关于Http这些的代码,我都能大概知道它在表达什么,要做什么。 Ret…

Retrofit源码角度来Http

前言

本篇Blog是Android深入Http的最后一篇。
也是是说写完本篇blog,我在Android关于Http的方面已经有了足够的开发基础了,以后至少见到关于Http这些的代码,我都能大概知道它在表达什么,要做什么。

Retrofit的低层实现是OkHttp,我们之前已经基本学习过了OkHttp,所以在看Retrofit时有一些内容会有相似之处。
我之前也对Retrofit的源码做过浅析:Retrofit源码浅析

里面最后一个部分写到了Retrofit和OkHttp的区别,为什么Retrofit的低层实现是OkHttp但是我们很少直接用比较低层比较细节的OkHttp而是更多的用Retrofit,最主要的是定位和职责不同。
举个例子吧,假如你整一个项目只用了一个网络请求,而且只在一个类里面用到了,那你还有必要去建立Api类然后写一个Retrofit的构建然后网络申请吗?那没什么必要,直接用OkHttp做个网络响应就可以了。又假如你整个项目,要申请几十个api,每个api都有线程切换的要求,那你花大量的时间去封装一个OkHttp工具类,那真的比封装Retrofit来的要低效的多很多。

我们主要讲其的结构,看Retrofit是怎么去做Http流程的。

首先我们看下官方文档对Retrofit的定义:
在这里插入图片描述
反正就是Android也能用Java也能用而且安全可靠的Http咯。不过现在Java的网络请求都是用Ajax吧。

Retrofit的官方示例

我们来看下官方文档给出的用法用例:
三步走:

  1. 先创建一个Java接口类,类里面声明了整个项目的所有Api调用,这些Api通过注解的方式描述出来
//Retrofit turns your HTTP API into a Java interface.
public interface GitHubService {@GET("users/{user}/repos")Call<ResponseBody> listRepos(@Path("user") String user);
}
  1. 创建一个Retrofit实例,通过其create方法去构造Api类的实例
//The Retrofit class generates an implementation of the GitHubService interface.
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").build();GitHubService service = retrofit.create(GitHubService.class);
  1. 拿到Api类的实例后就可以去实现网络请求了
//Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<ResponseBody> repos = service.listRepos("octocat");
//或者service.listRepos().enqueue(new Callback<ResoneBody>() {@Overridepublic void onResponse(Call<ResoneBody> call, Response<ResoneBody> response) {}@Overridepublic void onFailure(Call<ResoneBody> 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<JavaBean> listRepos(@Path("user") String user);
}

这就体现了Retrofit对响应体处理的强大。
我们来读Retrofit源码结构吧。

Retrofit大致源码解析

enqueue

我们以下面代码为例子:

 api.getRepo().enqueue(new Callback<List<Repo>>() {@Overridepublic void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {}@Overridepublic void onFailure(Call<List<Repo>> call, Throwable t) {}});

因为直接点进enqueue它是Call的抽象方法,而getRepo它也是个抽象方法,所以真正实现enqueue方法的应该是api对象里面的。
api又是由retrofit.create(Api.class)创建的,它创建了一个接口对象,所以我们去看create()方法,发现它终于是一个实现类了,也就是说这个方法它承接了后面所有的方法:

 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() {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<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);return serviceMethod.callAdapter.adapt(okHttpCall);}});}

Create()是整个Retrofit的核心

这个方法它创建出了一个ApiService的实例。ApiService明明是一个接口,却能实现了其声明的所有的网络请求。
这说明这个方法是真的很顶,能把你这个接口类的所有网络请求方法整的明明白白。

我们来一行一行的分析:
第一段:

 Utils.validateServiceInterface(service);

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

static <T> void validateServiceInterface(Class<T> 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.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 {...}});

看到了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<Object> 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<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);return serviceMethod.callAdapter.adapt(okHttpCall);

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

// CallAdapter.javaServiceMethod 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.javapublic 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());@Overridepublic void execute(Runnable r) {//就是使用Handler将结果返回到主线程handler.post(r);}}

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

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

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

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

part3中的第三行:

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

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

在OkHttpCall中有两行比较关键的代码。
①:创建一个OkHttp的Call,通过外面写进去的CallBack来构造

 @Override public void enqueue(final Callback<T> callback) {okhttp3.Call call;....if (call == null && failure == null) {try {call = rawCall = createRawCall();} ....

②:调用这个OkHttp的enqueue方法,去做后台的请求,那我们之前说过OkHttp的enqueue都会走那个 getResponseWithIntercptorChain(),然后通过响应来解析body。

 call.enqueue(new okhttp3.Callback() {@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)throws IOException {Response<T> response;try {//解析结果response = parseResponse(rawResponse);} catch (Throwable e) {callFailure(e);return;}callSuccess(response);}

然后根据结果来走onResponse。

最后的返回

return serviceMethod.callAdapter.adapt(okHttpCall);

主要是用来适配RxJava,如果我们没有使用RxJava,然后ApiService里面的返回都是Call,那没什么关系。

但是:
如果我们在创建Retrofit的时候加入了:

 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

然后我们在ApiService的方法返回把Call换成了Observable或者Single或者别的了:

    @GET("widget/getSearchDefaultWords#")Observable<List<Repo>> getSearchDefault(...);

那通过adapter就可以进行转换了。因为:

T adapt(Call<R> call);

只要是一个Call,我就可以给你一个Single、Observerable。主要是会给你切换线程。这就是adapter的作用。

总结

到这里,Retrofit就学完了。我其实根本就没怎么去碰源码。主要是了解其结构。
在这里总结一下它做了什么:

  • 使用动态代理newProxyInstance做了下面的事情:
  • Retrofit会解析我们写入的网络请求ApiService方法,成为一个 ServiceMethod 对象
  • 将这个 ServiceMethod 对象用来构建一个 OkHttpCall,这个OkHttpCall最后会走 enqueue()方法去进行网络请求并且解析Response
  • 将返回的 Call 通过 adapter()转换成为想要的返回对象(这个一般用在RxJava2里面)

所以Retrofit的大致结构是真的很简单,它本质还是走了OkHttp,但是它高度封装,并且多了线程前后台的切换和RxJava的适配、Gson的支持,使得本身作为一个网络请求来说特别适合用于项目。
所以它完全也是 Http在Android中的一个完美的应用。

到这里,我自己总结完了Http在Android中的学习,包括Http的原理、机制,Https的原理以及它所用到的 加密、授权、签名等等。在重温并巩固完这些知识后,我们在OkHttp中完全的用到了这些东西,而且一眼就能看到OkHttp的内部在做什么。
而Retrofit更像是一个专门为实际项目而生Http机制,它低层实现了OkHttp,所以它能实现网络请求,在这一基础上,它有添加了Android多个三方框架的支持,导致它在Android中网络上面的使用变得无比强大!它就是Android网络方面的一个霸主。

So,今天学完这部分,再去进而的学习RxJava,我就能真正的去做好一个实战项目了。

http://www.jmfq.cn/news/5159845.html

相关文章:

  • 关于网站建设新闻/新浪nba最新消息
  • 做外汇网站做什么类型网站好/百度极速版推广
  • 外包网站设计/百度推广登录首页网址
  • 娄底手机网站制作/网站的推广方法有哪些
  • 建立视频网站/东莞市民最新疫情
  • 湘潭城乡建设发展集团网站/太原seo外包服务
  • 深圳网站建设哪家公司好/百度平台客服电话
  • java 网站开发教程 pdf/晋江友情链接是什么意思
  • 网站设计开发软件网页美化工具/今天今日新闻头条最新消息
  • 音乐网站素材/推广代理平台
  • 那个网站可以接做网页私活/谷歌商店paypal官网下载
  • 电商网站开发哪里好/数字化营销怎么做
  • 中国林业工程建设协会网站/五八精准恶意点击软件
  • 纯css做网站/站长之家网站流量查询
  • 做贺卡的网站/电商网店
  • 荆州做网站公司/电脑培训班有哪些科目
  • 网站关键词搜不到了/百度快照优化培训班
  • 日本做外贸网站/上海百度推广优化公司
  • 网站建站售后服务/手机百度官网首页
  • 做网站建设公司crm在线/口碑营销的形式
  • wordpress暴力破解文件/优化网络搜索引擎
  • 快速 复制 建设网站/百度竞价培训班
  • wordpress后台忘记密码/西藏自治区seo 标题 关键词优化
  • 美妆网站建设方案/天津搜索引擎推广
  • 做网站的优惠广告/社群营销怎么做
  • 公司网站开发策划/如何在百度上投放广告
  • 网站建设微信托管/软文营销的概念
  • 大连网站前端制作公司/上海百度推广官方电话
  • 医疗网站建设信息/老鬼seo
  • 惠州网站建设选惠州邦/武汉百度快速排名提升