Retrofit使用入门
每当深入学习一个优秀的开源框架前,先了解它是干什么,怎么用。从最基本的使用开始,不断探索深处的实现原理。用OkHttp作了铺垫,顺理成章的该学一下移动开发中另一个热门框架:Retrofit。
1、Retrofit简介
Retrofit和OkHttp都出自大名鼎鼎的Square公司。算是亲兄弟了,OkHttp是哥哥,Retrofit是弟弟。关于OkHttp前段时间已经从头到尾看了一遍,从OkHttp的基本用法开始。
1.1、介绍
Retrofit是基于OkHttp封装的网络请求框架:网络请求由OkHttp完成,而Retrofit负责网络请求接口的封装。
GitHub:square/retrofit
Guide:Retrofit A type-safe HTTP client for Android and Java
1.2、引入依赖
强大的开源库往往只需要最简单的添加方式,就可以在项目中使用。开源库的版本查询详见Maven仓库搜索开源库。
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'除了Retrofit本体,还有附带的很多转换器Converter可以添加到项目直接使用(对应的版本去MavenCenter查):
//Gson
implementation 'com.squareup.retrofit2:converter-gson'
//Jackson
implementation 'com.squareup.retrofit2:converter-jackson'
//Moshi
implementation 'com.squareup.retrofit2:converter-moshi'
//Protobuf
implementation 'com.squareup.retrofit2:converter-protobuf'
//Wire
implementation 'com.squareup.retrofit2:converter-wire'
//Simple Framework
implementation 'com.squareup.retrofit2:converter-simplexml'
//Scalars
implementation 'com.squareup.retrofit2:converter-scalars'当然也可以自定义Retrofit的Converter转换器,随着Retrofit的不断深入了解,咱再解锁Retrofit的全部用法。
2、Retrofit快速入门
先从简单的上手,使用Retrofit实现最基本的GET网络请求。API使用本服务器搭建的:http://quibbler.cn:3000/。
2.1、创建Retrofit实例
和创建OkHttpClient有点类似,都采用建造者模式。通过内部Retrofit.Builder类创建定制的Retrofit实例:
val retrofit = Retrofit.Builder()
.baseUrl("http://quibbler.cn:3000/")
.addConverterFactory(GsonConverterFactory.create())
.build()服务端API根地址baseUrl必须非空,baseUrl在最后一步build()方法中校验,如果为空则构造Retrofit实例的时候抛出异常:
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
...
}所以在构造Retrofit实例的时候必须调用baseUrl()方法设置Retrofit的baseUrl。注意,还有一点,baseUrl必须要以 "/" 结尾,否则又会抛出异常。这就是阅读源码的重要性,不仅要知道异常会发生,还要知道为什么、从哪里抛出异常。
/**
* Set the API base URL.
*
* <p>The specified endpoint values (such as with {@link GET @GET}) are resolved against this
* value using {@link HttpUrl#resolve(String)}. The behavior of this matches that of an {@code
* <a href="">} link on a website resolving on the current URL.
* ... ...
* <p>Base URL: http://example.com/<br>
* Endpoint: https://github.com/square/retrofit/<br>
* Result: https://github.com/square/retrofit/
*/
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
//强制要求必须以 / 斜杠结尾
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}2.2、注解抽象API接口
Retrofit的核心之一就是注解,通过注解将网络请求抽象为接口。Retrofit框架共定义了25个注解,分别负责不同的功能。这里只是先简单演示一下,条条大路通罗马,至于其它注解以后再逐个了解它们的具体作用。
用HTTP网络请求最常用的GET方法对应的注解@GET定义一个接口:
interface SearchService {
@GET("search")
fun getSearchResult(@Query("keywords") keyword: String): Call<SearchBean>
}API请求接口必须定义为interface,通过Retrofit实例的create()方法创建接口实例的时候会校验是否是interface,若不是则抛出异常。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
...
}
private void validateServiceInterface(Class<?> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
...
}用注解定义好网络请求接口,就可以用2.1节定制好的Retrofit实例的create(final Class<T> service)方法获取接口实例。源码比较复杂 (涉及到反射、代理、各种设计模式等) 以后深入理解。
val searchService: SearchService = retrofit.create(SearchService::class.java)2.3、创建Call异步请求网络
服务端返回的数据是Json格式,所以我们将返回结果定义成对应的Bean类:SearchResult。推荐一个工具,可以一键生成Json对应的Bean:一键生成实体类插件:GsonFormatPlus。Retrofit请求网络后会使用Gson转换器GsonConverterFactory将响应直接解析成对应的SearchResult对象。
使用2.2节中获取到的API接口实例,调用接口中定义的方法获取Call<T>。此Call非OkHttp中的Call,随着源码的深入研究一切都会揭开。
val call: Call<SearchBean> = searchService.getSearchResult("周杰伦")获取到Retrofit框架中的Call<T>就可以发起网络请求,可以使用execute()同步请求,或者保留异步请求enqueue()。
call.enqueue(object : Callback<SearchBean> {
override fun onResponse(call: Call<SearchBean>, response: Response<SearchBean>) {
//在UI线程回调
}
override fun onFailure(call: Call<SearchBean>, t: Throwable) {
}
})注意一点区别:Retrofit的网络响应Callback是在UI线程回调,内部做了切换。而OkHttp默认是在子线程回调。
本篇结尾到这里,已经熟悉并能够使用Retrofit进行网络请求。作为一个开发者,只会调用开源库的API是远远不够的。接下来开始深入摸索Retrofit的注解、请求原理、设计模式及转换器等。
