前言

时至今日,Android的网络框架不再像之前那么到处都是,随着Google把 HttpClient直接删掉,似乎意味着Android越来越成熟。网络框架中的佼佼者Volley也不再那么光鲜,取而代之的是 Retrofit 和 okHttp。 
感觉很像 OnePiece 中白胡子的离去象征着时代的变革,新时代的开始,多弗的垮台象征着七武海制度的取缔一样,不会使用Retrofit + okHttp + RxJava等一系列技术,就迈不进新时代的门槛,也不足以称为一个合格的开发者。

哈哈闲话不多说了,只是在 Android这个平台上 开发这么长时间的一点感触。各位看看笑笑也就算了。还是来介绍 Retrofit 吧。(直接略过1.9)

本文的所有代码在 retrofitLearn;

1. Retrofit介绍

A type-safe HTTP client for Android and Java 
一个用于Android和Java平台的类型安全的网络框架

Retrofit is a type-safe REST client for Android built by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp. 
Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库。这个库为网络认证、API请求以及用OkHttp发送网络请求提供了强大的框架 。

Retrofit 把REST API返回的数据转化为Java对象,就像ORM框架那样,把数据库内的存储的数据转化为相应的Java bean对象。

那么我们知道Retrofit是一个类型安全的网络框架,而且它是使用REST API的,接下来我们看看什么是REST吧。

2. REST 介绍:

Resources Representational State Transfer 
资源表现层状态转化

  • 每一个URI代表一种资源
  • 客户端和服务器之间,传递这种资源的某种 表现层(“资源”具体呈现出来的形式,比如.txt,.png,.jpg)
  • 客户端通过四个HTTP动词(GET用来获取资源,POST用来新建或更新资源,PUT用来更新资源,DELETE用来删除资源)对服务器端资源进行操作,实现”表现层状态转化”

关于REST,这里只仅仅列出了结论,文末有超级好的链接,请查看。如果你所使用的API是REST的,那么恭喜你,这样的API看起来真的很舒服,庆幸的是我司就使用的是REST API。

知道了REST是什么,那接下啦就开始介绍Retrofit的用法啦。

3. Retrofit基本用法(未封装)

1.在build.gradle中添加依赖

//okHttp
compile 'com.squareup.okhttp3:okhttp:3.2.0'//retrofit
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.创建接口,声明API

//Retrofit turns your HTTP API into a Java interface.
//创建接口,声明GitHub的API
public interface GitHubAPI {/*请求该接口:https://api.github.com/users/baiiu*/@GET("users/{user}") Call<User> userInfo(@Path("user") String user);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.在MainActivity.onCreate()方法中调用

/*
1.初始化OkHttpClient
*/
OkHttpClient client = new OkHttpClient();/*
2.创建Retrofit
*/
retrofit = new Retrofit.Builder()//设置OKHttpClient.client(client)//设置baseUrl,注意,baseUrl必须后缀"/".baseUrl("https://api.github.com/")//添加Gson转换器.addConverterFactory(GsonConverterFactory.create()).build();/*
2.获取GitHub的API
*/
GitHubAPI gitHubAPI = retrofit.create(GitHubAPI.class);/*
3.异步调用
*/
Call<User> userCall = gitHubAPI.userInfo("baiiu");
userCall.enqueue(new Callback<User>() {@Override public void onResponse(Call<User> call, Response<User> response) {User body = response.body();LogUtil.d(body == null ? "body == null" : body.toString());}@Override public void onFailure(Call<User> call, Throwable t) {/*判断是否被cancel掉了*/if (call.isCanceled()) {LogUtil.d("the call is canceled , " + toString());} else {LogUtil.e(t.toString());}}});/*
取消调用
*/
//userCall.cancel();/*
同步调用,举个例子,写法如下(当然不能在主线程调用):
*///Each instance can only be used once, but calling clone() will create a new instance that can be used.
Call<User> clone = userCall.clone();Response<User> response = clone.execute();
User body = response.body();
LogUtil.d(body == null ? "body == null" : body.toString());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

注意: 
    1. 设置BaseUrl时必须后缀”/”,如 https://api.github.com/,这篇文章说的超清晰:Retrofit 2.0: The biggest update yet on the best HTTP Client Library for Android

2. 因为Retrofit在创建时候传入了BaseUrl,所以基本上所有请求都基于该BaseUrl了。但是总有些API不是以该BaseUrl开头的,特别是有些公司可能不是restful API的。那么该怎么办呢。Retrofit提供了一个注解@Url解决这个问题,可以在运行时直接使用该Url直接访问。代码如下:

//使用@Url注解,传入该Url地址就OK啦,跨过BaseUrl,直接访问该Url地址
@GET Call<Daily> getNewsList(@Url String url);
  • 1
  • 2

恩,接下来,知道了Retrofit的基本使用,接下来就是介绍Retrofit的注解了。

4. Retrofit注解

Retrofit使用注解来声明API的请求方式、请求参数等。这里只介绍一下它的 @Header 注解,其他的请阅读 官网文档 和 鸿洋的Retrofit2 完全解析 探索与okhttp之间的关系。和Retrofit 2.0 注解篇 
(这块写了也是翻译官方文档的和参考鸿样的,会拉长篇幅)

请求头的设置可以通过 @Header 注解添加,又有两种添加方式:

  • 设置静态的请求头。
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();@Headers({"Accept: application/vnd.github.v3.full+json","User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 动态的设置请求头。
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
  • 1
  • 2

Note that headers do not overwrite each other. All headers with the same name will be included in the request. 
同一个请求的同一个请求头在不同地方的设置不会被覆盖,而是会被全部添加进请求头中。

Headers that need to be added to every request can be specified using an OkHttp interceptor. 
如果要给每个请求都添加同样的Header时,可以使用okHttp的 Interceptor 。

那么,接下来就介绍Interceptor。

5.Interceptors使用

Retrofit 2.0 底层强制依赖okHttp,所以可以使用okHttp的拦截器Interceptors 来对所有请求进行再处理。

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

使用时,实现 Interceptor 接口,做我们自己的处理。 
目前使用中,一般用来设置UA设置缓存策略 、打印Log 等。这里介绍一个设置UA的Interceptor:

1.创建设置UA的Interceptor

public final class UserAgentInterceptor implements Interceptor {private static final String USER_AGENT_HEADER_NAME = "User-Agent";private final String userAgentHeaderValue;public UserAgentInterceptor(String userAgentHeaderValue) {this.userAgentHeaderValue = userAgentHeaderValue;}@Override public Response intercept(Chain chain) throws IOException {final Request originalRequest = chain.request();final Request requestWithUserAgent = originalRequest.newBuilder()//移除先前默认的UA.removeHeader(USER_AGENT_HEADER_NAME)//设置UA.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue).build();return chain.proceed(requestWithUserAgent);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

2.创建okHttpClient时 设置该Interceptor

okHttpClient = new OkHttpClient.Builder()//添加UA.addInterceptor(new UserAgentInterceptor(HttpHelper.getUserAgent()))//失败重连.retryOnConnectionFailure(true)//time out.readTimeout(TIMEOUT_READ, TimeUnit.SECONDS).connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS).build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Interceptors 和 Header 的配合使用让我们很方便的使用Http本身的缓存。之前用Volley的时候这块就比较难处理。解下来就说说Retrofit的缓存机制。

6. 配置网络缓存

使用Retrofit 感觉最方便的就是它提供的缓存方式(虽然这是Http本身的),我们可以随便通过Header和Interceptor配置自己的缓存策略。

6.1 缓存设置原理:

缓存的设置是通过设置 Http请求头和响应头中的 Cache-Control 的 max-age 属性达到的。在复写 Interceptor 时,通过设置响应头的Cache-Control 来达到目的。关于Http的本身的缓存命中请查看文末链接 (毕竟Http也是个大家伙) 。

6.2 缓存设置步骤

  1. 设置缓存目录 
    retrofit本身默认无缓存,连缓存目录都没有提供默认的,所以 要想实现缓存,必须要在创建OkHttpClient时设置缓存目录。这块超级坑,自己试了半天,最终看了下Cache那边的源码,竟然没有默认的缓存目录!!!

  2. 设置缓存的方式

    • 通过添加 @Headers("Cache-Control: max-age=120") 进行设置。添加了Cache-Control 的请求,retrofit 会默认缓存该请求的返回数据。
    • 通过Interceptors实现缓存。

6.3 实现Interceptor进行缓存

提供了两种缓存策略(参考),设置缓存时Application Interceptor 和 Net Interceptor 都要设置:

  • AllCachedInterceptor 
    有网没网都先走缓存,可以设置间歇时间。 
    同时可以针对某一个request设置单独的缓存时间,使用 @Headers("Cache-Control: max-age=120") 就行。

  • OnOffLineCachedInterceptor 
    有网可以不走缓存,可设定时间,设置为0意味着有网不走缓存,全部刷新数据;无网强制读取缓存数据。

到现在为止,关于Retrofit的基本用法和缓存设置已经了解了,写点例子就已经会用了,接下来肯定就是进行封装了,让它更便于调用。

7. Retrofit 封装

封装Retrofit是为了提供更方便的调用,更好的配置和使用。那么看到开头的Retrofit调用方式,大概有这么几个步骤: 
1. 创建OkHttpClient 
2. 创建Retrofit实例 
3. 获取我们写的API interface 
4. 在代码中异步调用

那么封装时候也肯定从这几步入手:

7.1 初始化OkHttpClient

创建OkHttpFactory类,初始化OkHttpClient并对外提供该实例的单例。并提供一个 HttpHelper 类用于提供所需要的参数,比如UA。 
这样做的好处是,程序中会使用OkHttp做一些其他请求操作,比如下载、上传等网络操作,就可用共用一个OkHttpClient。

这里使用枚举生成单例。

enum OKHttpFactory {INSTANCE;private final OkHttpClient okHttpClient;private static final int TIMEOUT_READ = 25;private static final int TIMEOUT_CONNECTION = 25;OKHttpFactory() {//打印请求LogHttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//缓存目录Cache cache = new Cache(MyApplication.mContext.getCacheDir(), 10 * 1024 * 1024);okHttpClient = new OkHttpClient.Builder()//打印请求log.addInterceptor(interceptor)//stetho,可以在chrome中查看请求.addNetworkInterceptor(new StethoInterceptor())//添加UA.addInterceptor(new UserAgentInterceptor(HttpHelper.getUserAgent()))//必须是设置Cache目录.cache(cache)//走缓存,两个都要设置.addInterceptor(new OnOffLineCachedInterceptor()).addNetworkInterceptor(new OnOffLineCachedInterceptor())//失败重连.retryOnConnectionFailure(true)//time out.readTimeout(TIMEOUT_READ, TimeUnit.SECONDS).connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS).build();}public OkHttpClient getOkHttpClient() {return okHttpClient;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

7.2 初始化Retrofit

依然使用枚举创建单例:

public enum RetrofitClient implements ApiContants {INSTANCE;private final Retrofit retrofit;RetrofitClient() {retrofit = new Retrofit.Builder()//设置OKHttpClient.client(OKHttpFactory.INSTANCE.getOkHttpClient())//baseUrl.baseUrl(GITHUB_BASEURL)//gson转化器.addConverterFactory(GsonConverterFactory.create()).build();}public Retrofit getRetrofit() {return retrofit;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

7.3 创建ApiFactory类封装所有API

如题,创建ApiFactory类管理所有的API interface,对外提供方法获取他们,这样调用时会方便很多,而且也便于修改。

public enum ApiFactory {INSTANCE;private final GitHubAPI gitHubAPI;private final AnotherAPI anotherAPI;ApiFactory() {gitHubAPI = RetrofitClient.INSTANCE.getRetrofit().create(GitHubAPI.class);anotherAPI = RetrofitClient.INSTANCE.getRetrofit().create(AnotherAPI.class);}public GitHubAPI gitHubAPI() {return gitHubAPI;}public AnotherAPI getAnotherAPI() {return anotherAPI;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这样封装在外部调用时会方便很多,比如:

    Call<User> userCall = ApiFactory.gitHubAPI().userInfo("baiiu");
  • 1

封装的代码在GitHub上:retrofitLearn;

这样封装自己觉得还不错,就可以开心的写代码啦。接下来说说一个神奇的工具。

8. Stetho 一个神奇的工具

首先:使用该工具需要翻墙。 不能翻墙的还是使用Charles吧。

  1. gradle中添加:
  compile 'com.facebook.stetho:stetho:1.3.1'compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
  • 1
  • 2
  1. 打开chrome,输入chrome://inspect 
    点击你的程序进行inspect,就可以直接使用Chrome进行抓包、调试你的应用啦。但是不能翻墙的话,你会看到一片空白。。。

结语:

毕竟Retrofit出来已经很久了,没有的赶紧用用吧。在使用Retrofit时,深深赶紧到其对Http本身机制的应用之深,真的感觉到非常棒的应用体验。用Retrofit作为网络框架,简直就能感觉到它设计之美,更何况还能和RxJava结合起来,美到不行。

参考:这些参考都值得一看的

  • 关于Retrofit的一本书 
    Retrofit — Basic Authentication on Android

  • retrofit介绍: 
    retrofit官网 
    Consuming APIs with Retrofit 
    Retrofit2 完全解析 探索与okhttp之间的关系 
    Retrofit 2.0: The biggest update yet on the best HTTP Client Library for Android 
    你真的会用Retrofit2吗?Retrofit2完全教程

  • Restful API介绍 
    理解RESTful架构 
    深入浅出REST

  • OkHttp 
    effective okHttp 
    Android OkHttp完全解析 是时候来了解OkHttp了 
    Android 一个改善的okHttp封装库

  • Interceptors 
    wiki-Interceptors 
    wiki-Interceptors 中文

  • 配置缓存 
    Retrofit2.0+okHttp3缓存机制以及遇到的问题 
    使用Retrofit和OkHttp实现网络缓存。无网读缓存,有网根据过期时间重新请求 
    浏览器 HTTP 缓存原理分析 
    浏览器缓存

  • 其他助于理解的 
    四种常见的 POST 提交数据方式

  • stetho 
    解决provisional headers are shown的过程

Android 网络框架 Retrofit2.0介绍、使用和封装相关推荐

  1. Android单元测试框架Robolectric3.0介绍(一)

    Android单元测试框架Robolectric3.0介绍(一) 作者 geniusmart 关注 2016.01.21 00:37* 字数 1550 阅读 18265评论 55喜欢 124赞赏 2 ...

  2. Android网络框架-OkHttp3.0总结

    一.概述 OkHttp是Square公司开发的一款服务于android的一个网络框架,主要包含: 一般的get请求 一般的post请求 基于Http的文件上传 文件下载 加载图片 支持请求回调,直接返 ...

  3. Android单元测试框架Robolectric3.0介绍(二)

    文章中的所有代码在此:https://github.com/geniusmart/LoveUT ,由于 Robolectric 3.0 和 3.1 版本(包括后续3.x版本)差异不小,该工程中包含这两 ...

  4. NoHttp开源Android网络框架1.0.0之架构分析

    转载于:https://www.cnblogs.com/brucemengbm/p/7091521.html

  5. android网络框架

    https://www.zhihu.com/question/35189851 个人比较推荐Square开源组合,用Retrofit(目前已经是2.0+)+OkHttp基本上已经可以处理任何业务场景了 ...

  6. 一个整合OkHttp 、Retrofit 、Volley 、RxJava、Novate多种开源网络框架的项目,高度的封装和集成,Android中Web网络请求一行代码解决

    一个整合OkHttp .Retrofit .Volley .RxJava.Novate多种开源网络框架的项目,高度的封装和集成,Android中Web网络请求一行代码解决 AndroidHttp 一个 ...

  7. ym—— Android网络框架Volley(终极篇)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看 Android网络框架Volley(体验篇) ...

  8. Android网络框架Volley项目实战-刘桂林-专题视频课程

    Android网络框架Volley项目实战-5257人已学习 课程介绍         使用Google 2013 I/O大会上发布的Volley请求框架做几个实战项目,归属地查询,QQ测试吉凶,天气 ...

  9. retrofit 2.0 android 教程,初识Retrofit2.0

    Retrofit无疑是当下最流行的Android网络请求框架了,是Square提供的开源产品.官方网站是这样介绍Retrofit的--A type-safe HTTP client for Andro ...

最新文章

  1. Spring Security原理与应用
  2. wdnas群晖nas_西数WD NAS红盘 WD140EFFX 14TB HDD和 SA500 1TB SSD开箱拆解评测
  3. 程序员:要想成为一个伟大的程序员
  4. Mac超强扒站神器——SiteSucker Pro 4.3.3 mac中英文
  5. python 交集_Python设置交集
  6. 【美赛】2022美赛思路参考资料及其代码分享【全网最全】【美国大学生数学建模竞赛】【MCM/ICM】
  7. 手机屏碎了,怎样辨别是外屏坏还是内屏坏,看完这篇文章就明白了
  8. MAC IDEA常用快捷键
  9. 如何通俗理解泊松分布?
  10. https端口必须443吗
  11. BigDATA面试题
  12. 我的世界科学计算机,在我的世界打造一台计算机有多难?复旦大神花了一年
  13. NewStarCTF 公开赛赛道 WEEK2 pwn 砍一刀
  14. java发送短信 短信平台
  15. Deep Spatio-Temporal Representation for Detection of Road Accidents Using Stacked Autoencoder
  16. swift 生命周期_iOS View的生命周期详解
  17. 【线下赛游记】2023 ICPC西安邀请赛 游记
  18. 外贸综合型企业解决方案丨汇信外贸软件
  19. 正大国家期货:期货交易系统中包括的四个要素
  20. CSS3动画 3DBOX

热门文章

  1. 通过STC12C5A08S2实战项目来理解单片机是怎么工作的
  2. 中公教育python教师_中公教育的教师水平怎么样?
  3. 安卓动画壁纸实战:制作一个星空动态壁纸(带随机流星动画)
  4. 部署Tomcat服务器
  5. HDU—校赛—1004
  6. table 手机 滑动_【推荐下载】html5手机端手指滑动选项卡滚动切换效果(转)
  7. 使用计算机研究生命科学的文章,现代若干科学前沿的计算主义哲学蕴意.doc
  8. html制作多媒体课件,多媒体课件设计与制作 教师课件制作平台
  9. v4l2框架—申请缓存(VIDIOC_REQBUFS)
  10. jpa blob mysql_Spring让BLOB 和Clob数据操作变得简单易行