从源码梳理Retrofit网络请求过程

通过定义一个接口,在方法上加入相关注解,Retrofit框架就可以把它解析成对应的网络请求,使用非常方便,记录下从源码角度看这个过程是怎么实现的。

一 Retrofit的引入

在Android Studio中引入Retrofit非常方便,目标最新版本是2.3,在app-build文件-dependencies节点下加入以下依赖即可:

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.0'

这里引入最后的两个依赖是为了与rx结合使用,可以先不加。

二 Retrofit是如何通过接口来生成网络请求的

首先,我们定一个接口,同时声明一个方法:

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

这里我们要请求github某个用户下的所有仓库。

调用很简单:

 ApiService apiService = retrofit.create(ApiService.class);
 Call<List<Repo>> solveBus = apiService.listRepos("SolveBugs");
 solveBus.enqueue(new Callback<List<Repo>>() {
           @Override
           public void onResponse(Call<List<Repo>> call,   Response<List<Repo>> response) {
                List<Repo> repoList = response.body();
                StringBuilder sb = new StringBuilder();
                for (Repo repo : repoList) {
                    sb.append(repo.getName());
                    sb.append("\n");
                }
                textView.setText(sb.toString());
            }

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

            }
  });
1.首先来看retrofit. create()方法

屏幕快照 2017-09-25 下午4.01.15.png

这个方法返回的是一个动态代理对象,当我们用这个对象调用listRepos方法的时候实际上会走到这里的invoke方法,在这个方法里,首先根据接口定义的方法,生成一个ServiceMethod对象,看一下ServiceMethod这个类的注释:

Adapts an invocation of an interface method into an HTTP call.

所以这个类就是一个关于http请求信息的封装。那么是怎么封装的呢? 主要逻辑在loadServiceMethod方法里。

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

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

逻辑很清晰,首先从缓存里取,如果没有的传入method(即我们声明的接口中的方法对象),通过build方法生成一个,然后放入缓存。 在build方法中,遍历method的所有注解,来取出其中的信息,比如请求方法以及地址等:

for (Annotation annotation : methodAnnotations) {
       parseMethodAnnotation(annotation);
}

屏幕快照 2017-09-25 下午4.12.36.png

拿到封装好的ServiceMethod对象后,构造一个OkHttpCall对象,以便与进行真正的网络请求(Retrofit基于OkHttp实现网络请求)。

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

回到最开始调用的地方:

这里真正调用的是okHttpCall对象的enqueue方法,这里进行的就是具体的网络请求操作了。

代码逻辑其实还是比较清晰的,主要是用到了很多设计模式,所以看起来可能有些费劲,里边儿的细节还要细细研究。(逃,继续看源码去)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Phoenix的Android之旅

Android UI开发利器-DataBinding

简单的说就是它提供了一种数据和UI绑定的方法,UI元素可以自动的根据数据的更新而自动改变。 在没有DataBinding的情况下我们是这么更新视图的, 先通过f...

613
来自专栏郭霖

Android安全攻防战,反编译与混淆技术完全解析(下)

在上一篇文章当中,我们学习了Android程序反编译方面的知识,包括反编译代码、反编译资源、以及重新打包等内容。通过这些内容我们也能看出来,其实我们的程序并没有...

2887
来自专栏lhyt前端之路

node框架express的研究0.前言1. 从入口开始1.1入口1.2 proto1.2.1 app.init方法1.2.2 app.handle方法1.2.3 每一个method的处理1.2.4

在node中,express可以说是node中的jQuery了,简单粗暴,容易上手,用过即会,那么我们来试一下怎么实现。下面我们基于4.16.2版本进行研究

623
来自专栏yang0range

关于单例设计模式

2.使用场景:确保某个类有且只有一个对象的常见,避免产生多个对象消耗过多的资源或者某种类型的对象只应该有且只有一个。

1283
来自专栏大闲人柴毛毛

三句话搞定适配器模式

适配器模式的官方定义: 将一个与当前类无法兼容的接口转换成能够兼容当前类的接口。 适配器模式的大白话: 现在有一个第三方类/我们项目组中别人写的类放在我们面前,...

3326
来自专栏流媒体

Android性能优化(TraceView使用)

看到第一行数据0(topLevel),topLevel包含整个trace周期。Incl Cup Time% 为100% 实际消耗cpu时间为1539.420...

613
来自专栏月牙寂

k8s源码分析-----kubectl(2)Factory

第一时间获取文章,可以关注本人公众号 月牙寂道长 yueyajidaozhang

6206
来自专栏jeremy的技术点滴

java中用好cache

2697
来自专栏java一日一条

Java接口回调机制详解

最近在看android fragment与Activity进行数据传递的部分,看到了接口回调的内容,今天来总结一下。

963
来自专栏专业duilib使用+业余界面开发

解决duilib使用zip换肤卡顿的问题(附将资源集成到程序中的操作方法)

1294

扫码关注云+社区