Android-Retrofit源码解析(一)调用流程(上)

Android Retrofit 源码分析_android retrofit解析 说一千道一万,不如自己去行动。要想在移动互联网的下半场是自己占有一席之地,那就得从现在开始,从今天开始,马上严格要求自己,既重视业务实现能力,也重视基础和原理。基础夯实好了,高楼才能够平地而起,稳如泰山。最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。还有。 阅读详情

我们知道,Retrofi的底层实际上是用OkHttp来进行网络请求的,本文也将会详细分析到OkHttp里面的调用链。

Retrofit基本用法

直接看官网https://square.github.io/retrofit/的例子。
首先创建一个GitHubService接口,这个接口定义了所有的网络请求。Repo是一个bean类,你可以在里面只定义一个String name;的变量。

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

然后在我们的自己的类中,创建一个Retrofit对象,并调用Retrofit.create方法创建GitHubService的实例。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

接下来调用GitHubService的方法,得到Call对象的实例。通过这个Call的实例可以发起同步或者异步请求。

Call<List<Repo>> repos = service.listRepos("octocat");

发起异步请求。

repos.enqueue(new Callback<List<Repo>>() {
   @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
              Log.d("MainActivity", response.toString());
    }

   @Override
    public void onFailure(Call<List<Repo>> call, Throwable t) {
             Log.d("MainActivity", t.toString());
    }
});

调用流程源码解析

1. 创建Retrofit对象的实例
Retrofit实例创建使用了Builder模式。Builder的代码比较简单。主要看一下其构造函数。

    Builder(Platform platform) {
      this.platform = platform;//Retrofit既可以用于Android端,也可以用于Java平台。platform指的就是这两个平台。
    }
    
    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;//Call对象的创建工厂。
      baseUrl = retrofit.baseUrl;//一般是域名

      // Do not add the default BuiltIntConverters and platform-aware converters added by build().
      for (int i = 1,
          size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
          i < size; i++) {
        converterFactories.add(retrofit.converterFactories.get(i));//变换器Converter列表。
      }

      // Do not add the default, platform-aware call adapters added by build().
      for (int i = 0,
          size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
          i < size; i++) {
        callAdapterFactories.add(retrofit.callAdapterFactories.get(i));//调用Service的方法返回的是Call对象如果不想要Call对象,例如与RxJava一起使用时,想要返回的是一个Observable对象,就通过传入一个RxJava的CallAdapter来实现。
      }

      callbackExecutor = retrofit.callbackExecutor;//调用Service方法后的回调。
      validateEagerly = retrofit.validateEagerly;
    }

2. Retrofit#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();
          private final Object[] emptyArgs = new Object[0];

          @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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

Retrofit#create()方法创建了一个GitHubService的代理类。

3. 调用GitHubService中的接口方法
调用GitHubService中的接口方法,其实执行的是代理类的invoke方法,也就是上面代码中InvocationHandler中override的invoke方法。我们先看一下loadServiceMethod(method)方法。

  ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这个方法返回了一个ServiceMethod对象。ServiceMethod是一个抽象类。调用ServiceMethod.parseAnnotations得到真正的实现类HttpServiceMethod。

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

实际执行HttpServiceMethod.parseAnnotations。这个parseAnnotations方法先通过CallAdapter拿到调用GitHubService要返回的类型,然后创建一个转换器Converter,将返回的数据流转换成目标类型。

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }

loadServiceMethod(method)方法拿到HttpServiceMethod的实例之后,就会执行其invoke方法。

 @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

Android7.0(Android SDK>=24)以上包括7.0,默认有两个CallAdapterFactory,一个是CompletableFutureCallAdapterFactory,一个是ExecutorCallAdapterFactory。Android7.0以下,只有一个ExecutorCallAdapterFactory。到底调用哪个CallAdapterFactory是根据我们在GitHubService中定义的方法的返回类型来确定的。
也就说,通过调用GitHubService接口的方法,一步一步到这里,调用的是ExecutorCallAdapterFactory/CompletableFutureCallAdapterFactory中生成的CallAdapter的adapt方法。
这里调用的是ExecutorCallAdapterFactory的adapt方法。

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

ExecutorCallAdapterFactory的adapt方法new 了一个ExecutorCallbackCall对象,直接return了。这个ExecutorCallbackCall实现了Call接口。后面我们执行call.enqueue操作时,实际就是执行的ExecutorCallbackCall里的enqueue方法。

整个前面这部分的思路可以说已经清晰了,简单总结一下:
调用Retrofit的create方法创建了我们定义请求的代理类,调用请求方法则是执行了CallAdapter的adapt方法,至于调用哪个CallAdapterFactory是根据定义请求接口的返回类型来选择的。默认会返回一个ExecutorCallbackCall对象。利用这个对象,我们可以发起同步或者异步请求。

由于篇幅太长,怕影响到阅读,后面发起请求部分的分析将放到下一篇来讲。

Android 网络框架之Retrofit源码解析 希望本文对你有所启发,有任何面试上的建议也欢迎留言分享给大家。好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。好了~如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。 阅读详情

相关推荐

Android网络编程(十一)源码解析Retrofit

最近博客的产出确实很少,因为博主我正在写一本Android进阶书籍,两头很难兼顾,但是每个月也得至少发一篇博客。上一篇我们介绍了Retrofit的使用方法,这一篇我们照例来学习Retrofit的源码。

Android进阶三部曲 - 刘望舒 5145

Android进阶知识:Retrofit相关

1.前言 Retrofit是什么?Retrofit是一个遵循RESTful设计的进行HTTP网络请求框架的封装,是现在Android端最火的进行网络请求的库。就像Volley是谷歌官方对HttpURLConnection和HttpClient的封装,或者像Github上许多开发者发布的对HttpURLConnection和OkHttp封装库一样,Retrofit也是Square公司发布的对OkHt...

weixin_30469895的博客 274

Android 网络框架之Retrofit源码解析,满满干货指导

算法知识点繁多,企业考察的题目千变万化,面对越来越近的“金九银十”,我给大家准备好了一套比较完善的学习方法,希望能帮助大家在有限的时间里尽可能系统快速的恶补算法,通过高效的学习来提高大家面试中算法模块的通过率。这一套学习资料既有文字档也有视频,里面不仅仅有关键知识点的整理,还有案例的算法相关部分的讲解,可以帮助大家更好更全面的进行学习,二者搭配起来学习效果会更好。部分资料展示:有了这套学习资料,坚持刷题一周,你就会发现自己的算法知识体系有明显的完善,离大厂Offer的距离更加近。【GitHub】

jixuczy的博客 1049

Android Retrofit源码解析

按照分析源码流程的“套路”,我们先来个例子: Api public interface SearchApi { @GET("/search") Call> search(@Query("key") String key); } 使用 Retrofit retrofit = new Retrofit.Builder() .bas

JohanMan的博客 1608

浅析ArcGis中的软件——ArcMap、ArcScene、 ArcGlobe、ArcCatalog

ArcMap:是集空间数据显示、矢量数据编辑、冲突数据检查(拓扑检查)、查询检索(地理编码)、统计(字段属性表)、报表生成、空间分析(ArcGIS Spatial Analyst)和高级制图(制图表达)等众多功能干一体的桌面应用平台软件。而且提供所见即所得的符号编辑器,令用户可以随心所欲地生成任意复杂的点、线、面符号。所支持的空间数据格式包括Arclnfo coverages、ESRI shapefiles、ArcSDE lavers、DXF、DWG、DGN、常见的图像格式、GRIDs、TINs等。

lxlmycsdnfree的博客 6566

carsim软件教学

第一步打开小锁(红色标注) 新手往往一看界面是灰的,界面内的各种模块打开不了,以为没激活成功 所有模块必须复制之后,进行编辑,不要直接进行修改(很重要) 2.空气动力学模型(红色标注) 这里面主要设定了簧上质量。整车的整备质量在下图模块中进行设定 空气动力学。主要涉及到空气阻力,在下面模块中进行设定,有个问题需要注意,他的空气阻力与汽车理论的空气阻力公式不一致,这一点需要注意 下面这会模块基本上用不到,涉及到一个声音和汽车的外观 下面这个模块主要涉及到发动机功率,传动比还有 tao,档位的传动比,发

weixin_43796045的博客 2551

Android Retrofit使用,内部执行流程

在我们开发过程中,会使用多种Http请求与服务器通信,上传或下载数据等。目前开源的Http请求工具也有很多,比如Google开发的Volley,Loopj的Android Async Http,Square开源的OkHttp或者Retrofit等。本文我们基于Retrofit 2(Retrofit 1.0的Api有较大的不同)来简单分析下。简介:A type-safe HTTP client fo...

CallmeZhe的博客 728

刷爆 Java 基础!1000 道经典面试题精解第一篇【序列化】

自定义序列化 / 反序列化的实现方式在实现接口的类中,手动重写和方法在方法内优先调用执行默认序列化逻辑;追加自定义逻辑(如敏感数据加密、临时字段赋值、兼容旧版本数据等)。// 序列化ID,保证兼容性// 敏感字段,默认不序列化,自定义处理// 自定义序列化// 执行默认序列化:写入username// 自定义逻辑:密码加密后写入// 自定义反序列化// 执行默认反序列化:读取username// 自定义逻辑:读取加密密码并解密// 模拟加密/解密工具方法。

七叔的博客 192

Android Retrofit 2.0(三)从源码分析原理

Retrofit·特点性能最好,处理最快使用REST API时非常方便;传输层默认就使用OkHttp;支持NIO;拥有出色的API文档和社区支持速度上比volley更快;如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。默认使用Gson系列文章推荐:Android 必须知道网络请求框架库,你不可错过的介绍篇Android Retrofit 2.0(一)...

csdn_aiyang的博客 1万+

解决微信小程序长页面滚动到底部点击底部的输入框后输入框漂浮且页面滚动到顶部

一、问题描述 项目中有一个长页面上部展示部分信息下部为信息录入,页面长度为三屏幕(不同手机屏幕大小略有差异),当滚动到第二屏或者第三屏去填写信息时点击输入框后输入框漂浮起来了并且页面向上滚动了一段距离,回到了第一屏中展示的内容。效果如图。 滚动到第二屏,证件号输入。 点击输入框 可以看到证件号输入框漂浮了起来并且页面滚动到了第一屏展示的内容。 注意:小程序是2018年上线,在2020年4月份之前该页面从未出现过这种现象。推测:微信的后续更新中对微信小程序基础库进行了重构,导致点击输入框后页

仰望星空的代码 3261

【手把手教学】YOLOv13的Dilated Reparam Block (DRB) 实现细节与优化技巧

DRB(Dilated Reparam Block)是一种创新的卷积神经网络模块,通过多分支膨胀卷积和结构重参数化技术显著提升模型性能。训练阶段使用不同膨胀率和卷积核大小的并行分支增强特征提取能力,推理阶段则将这些分支融合为单一高效的大核卷积。该方法成功解决了大核卷积的计算复杂度和训练困难等问题,在保持推理效率的同时,使模型准确率提升8.56%,mAP暴涨12.33%。DRB的核心在于训练时复杂、推理时简单的设计哲学,以及膨胀卷积的多尺度特征提取能力,为CNN性能优化提供了新的思路。

FJN110的博客 558

Android 网络编程:Retrofit源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载 文章分类:Android知识体系 - 网络编程 复制代码一、前言 Retrofit是一个基于OkHttp、遵循RESTful API设计风格的网络请求封装框架,本文将按照其工作流程逐步分析对应的源码(本文使用的Retrofit版本为2.5.0) 二、源码分析 1. 请求示例 以下是一次简单的请求示例,首先我们需要定义一个接口API,并使用注解描...

weixin_34254823的博客 279

高通平台蓝牙学习-- 基于WCN6750 Bluetooth 5.2的讲解

摘要:蓝牙5.2解决方案WCN6750具备多项先进特性:完全兼容5.2标准及ANT+协议,支持2Mbps高速BLE和长距离传输;采用射频集成方案,与WLAN共享天线并支持5G并发;内置功率放大器,支持Class1/2传输;提供双音频流和Slimbus接口优化。其HCI UART接口支持3.2Mbps速率,通过BlueZ协议栈实现蓝牙5.2功能,包括2Mbps模式和长距离传输,符合核心规范要求。(149字)

专业开发者的博客,一个从事Android WiFi和蓝牙的工程师 3万+

Android-Retrofit源码解析(一)调用流程(下)

调用流程分析 上篇文章Android-Retrofit源码解析(一)调用流程(上)分析到了调用enqueue之前,接着往下走。 repos.enqueue(new Callback&amp;amp;amp;lt;List&amp;amp;amp;lt;Repo&amp;amp;amp;gt;&amp;amp;amp;gt;() { @Override public void onResponse(Call&amp;amp;amp;lt;List&

HuangLin的博客 395

北斗导航 | 卡尔曼滤波与因子图优化对比(附图优化matlab代码)

- 历史数据利用:因子图通过滑动窗口保留历史状态,优化时联合多帧数据;卡尔曼滤波仅依赖当前和上一帧状态 。 - 迭代优化:因子图通过多次迭代逼近最优解,卡尔曼滤波仅单次更新 。 - 误差抑制:因子图的多次线性化可有效抑制非线性误差(如GNSS伪距观测的非线性) 。

尘世冰封的专栏 1306

ANSYS——模态分析的理论基础

ANSYS模态分析理论基础

python_AI_fans的博客 9095

展开说说Android之Retrofit详解_源码解析

本文主要从六个方面分析了Retrofit源码实现:首先介绍了Retrofit的核心类和接口,包括Retrofit类、ServiceMethod类等;接着解析了@GET、@POST等注解的作用;然后通过OkHttpCall类揭示了Retrofit封装OkHttp的实现;解释了Retrofit异步请求能在主线程返回的原理;梳理了请求的完整流程;最后总结了Retrofit的优缺点。文章详细呈现了Retrofit从注解解析到最终请求实现的完整机制,特别是通过动态代理和线程切换的实现细节

Hidanchaofan的博客 1034

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android-retrofit源码解析

retrofit是目前比较流行的网络框架,但它本身并没有网络请求的功能,网络请求的功能是由okhttp来完成的。retrofit只是负责网络请求接口的封装,让我们更加方便的请求网络。在对retrofit框架进行了解之前,我们需要先了解okhttp,另外retrofit涉及到的设计模式很多,我们主要要了解动态代理模式和适配器模式。Android-okhttp详解-优快云博客Java 代理模式之静态代理与动态代理_java静态代理模式-优快云博客。

袁震的博客 1288

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android Retrofit 源码解析

一、前言 前面的一篇文章《Android OkHttp 源码解析 - 整体流程分析》已经对 OkHttp 网络请求框架有一个大概的了解。现在我们来学习一下 Retrofit。Retrofit 是 square 公司的另一款广泛流行的网络封装框架,它是对网络请求的封装,不是一个网络框架,retrofit 里面网络框架还是由 okhttp 内核来做。 今天同样地对 Retrofit 的源码进行详细...

lerendan的博客 817

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Android进阶必学retrofit源码解析

源码的分析将从基本的使用方法入手,分析retrofit的实现方案,以及其中涉及到的一些有趣的技巧。public interface GitHubService { @GET(“users/{user}/repos”) Call listRepos(@Path(“user”) String user); }Retrofit retrofit = new Retrofit.Builder() .baseUrl(“https://api.github.com/”) .build(); GitHubSe

2401_83704218的博客 690
上一篇: Android-Glide源码解析(一)调用流程
下一篇: Android-Retrofit源码解析(一)调用流程(下)
Huang-Lin
博客等级 码龄10年 20粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值