简要分析Retrofit框架实现

retrofit整体代码量不是很大,但是涉及到的知识点还是很多的,也是一款很好的解耦封装框架,在其中是能够学习到很多东西的,当前鉴于时间原因先重点分析retrofit的流程逻辑实现,里面的涉及到的知识点后续会有文章分析学习(水平有限,有些可能分析不到位,欢迎小伙伴指正讨论,喷就没必要了吧)。

  1. 从组建者模式浅谈retrofit对象的组建


    retrofit实例创建
  • 如上代码所示,retrofit很明显是build(组建者模式),组建者模式特性:
        * builder模式通常对象内部存在builder组建类,通常是static修饰,可以通过对象直接访问,还可能设置成为final,不能被继承修改。
        * builder内部属性api通常是链性的,可以链式调用
        * builder除了内置属性设置外,比较特殊的就是构造方法和组建方法build(),retrofit我们也是重点分析这两个api。
  • 构造方法Builder():


    retrofit builder api

    承接上文

        * 如图所示:下面的builder构造方法接受platform作为参数,而上面而是传入的platform.get(),继续向下跟Platform这个对象做什么用:


    Platform的get api
        * get返回的静态变量PLATFORM,找到改变量的初始化方法findPlatform();跟进去方法如下:
    findPlatform()
        * api方法代码很简单也不麻烦就是校验了是否是Android平台若Android平台返回了Android对象,非Android平台返回了platform示例,我们当前分析Android,重点看一下Android对象的实现,即:
    Android对象

        * 通过Android handler实现的默认回调线程是Android的ui线程。在Android平台retrofit会将响应的数据自动切回到ui线程,所以使用rxjava+okhttp+retrofit要切实分析其接口请求和接口响应都在那一个线程中,不然极其容易出问题,接口请求通常要么是rxjava(外部线程处理)或者okhttp异步处理,retrofit是不处理接口请求的线程逻辑,但是retrofit是处理了接口返回的线程(无论请求什么线程都会将响应切回UI线程)。

  • builder对象通过一系列的set api对其属性进行设置赋值,具体api在上面图片介绍上都添加了注释,不再一一解释。
  • builder即时没有设置其属性,在对象组建方法build中每一个属性也有其对应的默认赋值,build方法如下:


    build方法实现

        * 简要分析api的实现,外面用户没有设置的情形下,判空后将callFactory指向了okhttpClient,后续callAdapter和CovertAdapter都将默认的实例类添加到了对应的list列表中去。

  • 由上面的步骤我们就获取到了retrofit的示例对象,将设置其对应的上下文环境,默认的call示例和默认的covert实例。
  1. 通过反射,注解,抽象代理等技术retrofit创建声明的接口的一个实例对象并实现内部的api方法,根据方法的注解将其封装到okhttpcall对象。


    retrofit创建抽象接口对象
  • 这一块是retrofit的核心代码,也是难点最多的代码,涉及到java的反射,注解等,设计模式的抽象代理,水平有限这一块只能说一下个人的简单理解,更多的是流程逻辑的实现,具体细节实现分析后续单开文章消化解析。
  • 由上面的可知入口方法是create,下面是create的代码实现:
    create方法实现
  • api首先对于创建的类进行校验处理,即validateServiceInterface的实现:
    validateServiceInterface
        * 如图所示对于api的重点逻辑已做标识处理,不再详述,getTypeParameters
  • 通过抽象代理创建接口的实例对象及其对应方法的实现,这一块当前还不熟暂不详细分析,这段代码流程逻辑是先反射实现声明的方法,然后校验方法是否是默认方法,java对于默认方法的理解是有具体的实现的方法就是默认方法,接口中一般声明的都不是默认方法,所以第三个圈中不会处理,会直接走到loadService方法,这方法上面校验接口类的时候又出现,主要处理了方法的注解解析。下面跟着去看这个方法的实现:


    loadService
  • 方法使用容器及类单例实现了方法的唯一,这个后续有篇文章分析使用容器实现多方法或者多对象的唯一性实现
  • 抛去上面描述的,方法的核心实现集中在ServiceMethod.parseAnnotations(this, method),继续向下跟:


    ServiceMethod
  • 这个api方法比较简单明了,主要做个两步:
        * 将接口中声明的注解http协议,header协议,接口参数等解析并封装到对应的RequestFactory中去。
        * 将上面的requestfactory和method和retrofit串联起来,包括calladapter(回调类型),covertadapter(回调数据转换)和okhttpcall绑定在一起。
  • 当篇文章简单分析retrofit的实现能够更有利于后面的retrofit的使用和学习retrofi的实现思路,后续两个api就不跟了,后面注解的详细解析及其串联绑定,上面的流程也更流畅。
  1. rotrofit如何实现同步和异步接口请求访问的


    retrofit的请求实现
  • 由第二个小章节可以知道接口访问retrofit最终是关联到okhhtp,这个章节可以更好的验证retrofit将最后的接口请求还是交给okhttp处理的,首先看一下call的api集合:


    call抽象接口

    如图所示,接口中定义了两个api一个是execute另一个是enqueue,这两个表示同步和异步调用看api就和okhttp的同步/异步接口访问很相似。

  • 接下来重点去看call的okhhtp实现类okhttpcall对其api的实现,即:
    okhhtpcall的execute的实现

        * okhhtpcall创建后只能执行一次这个逻辑和okhhtp也很相似,第一步先是验重,校验当前是否已经执行过。
        * okhttpcall是否创建失败根据其失败类型返回不同的异常报警。

        * 创建okhttp的call对象,createRawCall的具体实现是:
    createRawCall的实现

        * 调用上面创建的okhttp3的call对象的execute方法将接口请求交接给okhhtp处理并获取其response进行后续的解析,解析流程下个章节再去分析。
  • enqueue异步调用和同步execute流程基本类似。
  1. okhttp响应数据怎么转换成为retrofit对象的


    responce响应解析
  • 代码比较简单也比较清晰,就是对okhttp请求后的响应数据进行解析并根据不同的响应码对上层进行响应,即:
        * http响应码成功都在200到300之间,所以不在此范围内的响应接口失败并将对应的响应数据对外提供
        * 204/205两个响应码比较特殊,是接口成功但是没有具体的响应数据,此时直接对外响应成功并将数据对外响应,不进行转换。
        * 针对200的其他情况,将其封装到ExceptionCatchingResponseBody中去,该封装类持有responsebody并对其进行读取并获取内容类型和内容大小,内容不可读则进行异常抓取。
        * 上一步没有出现异常的情况下进行下一步的逻辑操作,将其交给转换器进行转换操作。
        * 异常校验封装类和平时写法不太一样,平时通常都是和下面的convert同时写到一个try catch中去,仔细想想好像也没什么不同。
        * 将转换后的对象响应给用户。

参考文章:
retrofit相关源码解析
深入浅出retrofit
深入读懂retrofit

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容