Posted on Leave a comment

Retrofit、Volley、HttpClient比较

Retrofit作为现在大家用的最多HTTP请求框架,非常流行,Github上star 3w+。它为什么能超越Volley、HTTPClient能够一枝独秀呢?那先看看其他两个HTTP栈的实现。

HTTPClient-Java界老牌HTTP栈实现,由Apache维护,它支持HTTP1.0/1.1、极其丰富的API来支持各种子协议,代码庞大臃肿也变成了它的缺点,虽然它的创建一开始是为了弥补Java SDK中java.net包HTTP请求的简单实现,Android在6.0以后彻底弃用了它,转而推荐使用HTTPURLConnection。我

Volley-作为Google官方开源的一款HTTP栈,它支持切换HTTPURLConnection、HTTPClient底层协议栈的切换,同时提供了请求线程池、缓存的支持,刚一推出也是收获许多赞赏,但是它就像G家好多产品一样,几年一次的维护和有些bug都需要使用方去维护解决,都是开发者逐渐抛弃的原因。虽然从Volley开始,这些HTTP栈的实现都在逐渐向上层实现,因为不管是Android、iOS大部分App的网络交互都是Restful-API的实现,所以能在提供基础HTTP服务的基础上,提供请求内容的封装、响应内容的解析就越来越迫切,Volley在这方便做出了第一步,响应内容的解析以及支持自定义解析这些功能。但是Volley的致命问题在于它的响应内容处理上,必须将全部数据读取出来交给上层数据,这对内存的要求可能很高,缺乏一定的灵活性,所以只适合小数据量的HTTP请求。

Retrofit-来自Android界开源大厂Square.Inc ,底层HTTP栈来自于OKHTTP框架,它支持HTTP 1.1/2,支持TLS,HTTP2作为socket连接复用的最新技术,OKHTTP的支持可以说是一大重点,因为作为移动端App,相比浏览器中的Web开发,App端点的可控性可以让我们快速支持这种技术来提高加载速度,同时OKHTTP提供了请求拦截器方便我们在请求发起前的对参数进行操纵。

Retrofit建立在OKHTTP的基石之上,抽象出了Converter、CallAdapter这两个重要的概念。

Coverter作为HTTP请求、响应内容的类型服务类为上层不同的技术实现提供支持,现在支持GSON、Guava、JSON、XML、Protobuf,同样你可以根据自己的需求进行定制。

CallAdapter则为不同的上层框架提供了容器支持,让你能够在Retrofit的基础上同步、异步的分发请求与响应,现在支持Java8、RxJava、RxJava2的标准实现。

除此之外,动态代理、注解编程的使用,让开发者从复杂的请求参数、URL拼接中解放出来,更多的去关心业务逻辑的实现。

这一系列的优势让Retrofit逐渐得到开发者的青睐。

番外:

在Java11 OpenJDK的文档中看到另外一个HTTPClient的实现,支持HTTP2、支持上层RxJava编程,但这对于Android平台来说JDK 11还是有点远。

参考资料:

https://square.github.io/okhttp/

https://openjdk.java.net/groups/net/httpclient/intro.html

Posted on Leave a comment

SVG Path命令属性

Android从5.0开始支持SVG矢量图,通过Vector Asset工具将SVG文件转换VectorDrawable定义的XML文件中,在运行时inflate这个xml文件来绘制图层,这对于减小APK资源文件体积和避免混乱的分辨率支持上都有很好的效果,同时Android通过Support支持库的形式给予了低版本的支持。

Android上对SVG的支持是受限制的,仅支持SVG tiny1.2版本的属性和标签,而且不支持text标签。

path标签是SVG中最常用的标签,这其中最重要的属性就是d(command)属性,它标明这个路径的绘制起点、终点、中间路径关键点、两点之间是否为直线、弧线、贝塞尔曲线等等。

d(command)属性主要分几类:

起点

M、m来表示,如M150,0

表示从path的起点, 从x-150,y=0的坐标起点开始绘制

终点

Z、z来表示,无参数

表示path的终点,链接到path的起点,闭合path,然后结束绘制

直线

假设当前点坐标为(10,10)

L、l表示直线线段,如L100,100,表示从(10,10)开始,绘制一条到(100,100)的直线线段

H、h表示水平线段,如H100,表示从(10,10)开始,绘制一条到(100,10)的水平线段,等同于L100,10

V、v表示垂直线段,如V150,表示从(10,10)开始,绘制一条到(10,150)的垂直线段,等同于L10,150

三次贝塞尔曲线

假设当前点坐标为(100,200)

C、c表示三次贝塞尔曲线,如C100,100 250,100 250,200,表示起点坐标为(100,200),控制点1坐标为(100,100),控制点2坐标为(250,100),终点坐标为(250,200),绘制这一条三次贝塞尔曲线线段。

S、s也表示贝塞尔曲线,只是它比较特殊,它的控制点1来自于上一条C、c、S、s曲线的控制点2坐标与上一条C、c、S、s曲线终点坐标连线上的对称点,

就如上面的例子,S曲线的控制点1坐标就为(250,300),这样的曲线在连贯性上是平滑曲线,所以也称为是平滑三次贝塞尔曲线;

如果上一条线段不是C、c、S、s三次贝塞尔曲线,那么默认它的控制点1坐标与起点坐标一致;

如S400,300 400,200,假设沿着上一条S贝塞尔曲线继续绘制,则起点坐标为(250,200),控制点1坐标为(250,300),控制点2坐标为(400,300),终点坐标为(400,200)。

二次贝塞尔曲线

假设当前点坐标为(200,300)

Q、q表示二次贝塞尔曲线,如Q400,50 600,300,表示起点坐标为(200,300),控制点坐标为(400,50),终点坐标为(600,300),然后绘制一条二次贝塞尔曲线线段。

T、t也表示二次贝塞尔曲线,如同S、s平滑三次贝塞尔曲线一样,它“借用”了上一次二次贝塞尔曲线的控制点,取上次曲线控制点与上次曲线的终点坐标连线上对称点为新的控制点;

如果上一条线段不是Q、q、T、t二次贝塞尔曲线线段,那么默认它的控制点坐标与起点坐标一致。

如T1000,300,假设沿着上一条Q二次贝塞尔曲线继续绘制,则起点坐标为(600,300),控制点为(800,550),终点坐标为(1000,300)。

椭圆曲线

假设当前点坐标为(50,-25)

A、a表示椭圆曲线,如a25,25 -30 0,1 50,-25 l 50,-25,表示椭圆半径rx=25,ry=25,x轴方向上的旋转角度-30。

 

参考资料:

https://svgwg.org/svg2-draft/paths.html

https://developer.mozilla.org/en-US/docs/Web/SVG

Posted on Leave a comment

Blink内核相关术语、映射关系

在读Adblock Plus for Chrome插件的源代码时,拦截入口处有几个判断非常重要,这涉及到当前打开Tab的URL、来源、打开方式等概念,对应到Blink中术语有page、main frame、iframe、document等,翻阅一下Blink的README文档,找到官方的介绍在此做一下记录。

  • Page

一个Page对应于一个Tab,当然前提时OOPIF(Out-of-Process iframes)没有开启。每一个渲染进程可能包含多个Tab。

  • Frame

Frame对应于HTML中的frame,可能是主frame或者iframe,每个Page在树形结构中可能包含一个或者多个frame。

  • DOMWindow

一个DOMWindow对应Javascript中的一个window对象,每个Frame有一个DOMWindow。

  • Document

一个Document对应Javascript中的一个window.document,每个Frame有一个Document。

  • ExecutionContext

一个ExecutionContext是一个抽象概念,在渲染进程的主线程中对应于一个Document,在工作者线程中对应于一个WorkerGlobalScope。

解释完这些,那就知道相互之间的对应关系了。

  • 渲染进程:Page=1:N
  • Page:Frame=1:M
  • Frame:DOMWindow:Document(ExecutionContext)=1:1:1,这在某个时刻是成立的,因为某个时间段内涉及到iframe的locatio跳转新建frame以及frame的重用问题。