一、前期基础知识储备
我们先来列举一下常见的网络框架:
Afinal——作者已经停止更新,不推荐使用。本身也是聚合性框架,不推荐;
Android-async-http——基于Apache HttpClient,Android6.0就用不了了,不推荐;
xUtils——作者已经停止更新,不推荐使用。本身也是聚合性框架,不推荐;
OkHttp——相对成熟的解决方案,Android6.0(2015年)中底层源码就开始使用;
Volley——谷歌官方提供,适用于数据请求频繁的场景,但下载上传表现很差;
Retrofit——根据OKHttp封装的框架,作为简化 HTTP 请求的库,已经运行多年。
如果以上后三种网络库你都能熟练掌握,那么优先推荐使用 Retrofit。
注;OkHttp和Retrofit都是Square提供的,这个公司的框架都比较简洁,还有他们只招处女座。
二、Retrofit知识点讲解
(1)官方描述:Type-safeHTTP client for Android and Java by Square.
官网地址:http://square.github.io/retrofit/
Github地址:https://github.com/square/retrofit/
(2)Retrofit实质
retrofit英文释义:改进、更新、翻新
Retrofit 是一个RESTful 的 HTTP 网络请求框架的封装。我们的应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,后者根据用户的需求对结果进行解析的过程。
所以Retrofit实际上是OkHttp的“更新”。
——————————————我是重点分隔线——————————————
(三)上代码 具体实现
Build.gradle中添加依赖:
implementation .squareup.retrofit2:retrofit:2.1.0'
// Gson转换器,将网络响应使用Gson转换成Java Bean
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
注意,网络上数据交换类型通常使用的都是Json,所以这里为Retrofit配置了Gson转换器。然后再代码中创建Retrofit实例时。配置好Gson转换器,这样就可以直接将返回的Json文件转换为Java Bean了,十分方便。
运用retrofit实现一次基本GET类型的网络请求———分三步走:
①将一个Http API转化为一个Java接口;
实现一个GET请求,请求的网址是https://api.github.com/users/{user}/repos;
//定义一个接口————将http api转化为Java接口
public interface GitHubService {
@GET("users/{user}/repos")//@GET表示我们的请求方式是get请求
// 返回数据为Call<T>对象,泛型T表示网络解析后结果的类型
Call<List<Repo>> listRepos(@Path("user") String user);//在发起请求时, {user} 会被替换为方法的第一个参数 user
}
这里出现了一些新的东西:
1)注解-@GET ,这是Retrofit以注解的形式发出的GET请求,()中的参数是一个Value,用于传入url;
2)返回的数据类型-Call< T>,表示返回体中的数据,这里返回的Call是用来让我们执行请求的;
3)方法-listRepos(),表示该接口中定义的方法;
4)注解-@Path,这是Retofit的另一种注解。
②构造retrofit实例,得到返回的数据结果;
//构造Retrofit,得到一个retrofit实例对象 然后创建接口的实例对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/") //基础URL 建议以 / 结尾
.addConverterFactory(GsonConverterFactory.create()) //设置 Json 转换器
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> call = service.listRepos("octocat");//最后接口的实例对象再返回一个类似的 返回的数据结果
这里也出现了一些新的东西:
1)baseUrl,表示传入的url,和上面接口中value一起构成完整的url,最好在这个地址中使用 “/” 作为结尾;
2)service,这个service不是四大组件的service,而是接口的实例对象;
3)create(),这个方法里传入的就是由Http api转化的Java接口类。
接口的实例对象service,调用接口中定义的方法 listRepos(),传入需要的参数"octocat",最终完成一次Http请求,拿到返回的数据结果。
另外,需要注意的是,这里构建Retrofit实例时,记得配置好Json转换器。如果没有给Retrofit配置网络响应的解析器会造成类型转换的错误。
③同步/异步执行Http请求;
在AndroidManifest中添加网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
使用Retrofit实现的GithubService对象githubService,调用接口方法获取一个Call对象,然后使用该对象发出同步/异步网络请求:
//同步调用
List<Repo> data = call.excute();//execute 方法只能调用一次
//异步调用——最后用得到的call对象来执行http请求
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Response<List<Repo>> response, Retrofit retrofit) {
Log.e(TAG, "onResponse: "+response.body().getLogin() );
}
@Override
public void onFailure(Throwable t) {
Log.e(TAG, "onFailure: " + t.getMessage());
}
});
请求返回结果:
①如果直接访问https://api.github.com/users/{user}/repos,结果如下:"message": "Not Found"
{
"message": "Not Found",
"documentation_url": "https://developer.github.com/v3/repos/#list-user-repositories"
}
②retrofit实例对象传入参数 "octocat"替换{user}之后,访问网址为https://api.github.com/users/octocat/repos
返回的结果如下: 可以看到有非常多的Json数据
至此网络请求就成功了。当然,Retrofit还有更多的使用方式,我们还可以配置请求的查询参数,请求头,请求体,表单提交,文件提交,另外还可以配置其他的数据类型转换器。
提一句,快速生成Java Bean类,如下,这是将https://api.github.com/users/octocat/repos返回的Json数据放置在Json网站解析后的图片:
可以看到,实际由一个集合组成,里面包含多个实例对象。所以文中设计的返回数据类型为List<Repo>,然后利用Json网站自动转换Java Bean的功能,自动创建一个实体类,减少手动创建的过程(实际网络返回的Json数据格式庞大,手动创建重复劳动且容易出错)。
Json解析,自动转换网站:https://www.sojson.com/json/
或者使用Android Studio自带的插件GsonFormat。
实体类的创建在使用Retrofit的过程中是非常重要的,因为这关乎到创建Retrofit接口时,接口方法返回的数据类型。
(4)Url配置:
因为Url配置这个地方,有比较多的实现方式,所以单独拿出来讲。
Retrofit 支持的协议包括GET/ POST/ PUT/ DELETE/ HEAD/ PATCH,当然在开发中,我们最常用的就是GET/POST请求。这些协议均以注解的形式进行配置,比如我们已经见过 GET 的用法:
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
在发起请求时, {user} 会被替换为接口方法的第一个参数 user。
这些注解都有一个参数 value,用来配置其路径,比如示例中的 users/{user}/repos,我们还注意到在构造 Retrofit 之时我们还传入了一个 baseUrl("https://api.github.com/"),请求的完整 Url 就是通过 baseUrl 与注解的 value(下面称 “path“ ) 整合起来的,具体整合的规则如下:
path 是绝对路径的形式:
path = "/apath",baseUrl = "http://host:port/a/b"
Url = http://host:port/apath
-----------------------------------
path 是相对路径,baseUrl 是目录形式:
path = "apath",baseUrl = "http://host:port/a/b/"
Url ="http://host:port/a/b/apath"
-----------------------------------
path 是相对路径,baseUrl 是文件形式:
path = "apath",baseUrl = "http://host:port/a/b"
Url = "http://host:port/a/apath"
------------------------------------
path 是完整的 Url:
path ="http://host:port/aa/apath",baseUrl ="http://host:port/a/b"
Url = "http://host:port/aa/apath"
本例中的url设置采用的是第二种方式,在开发中也建议采用第二种方式来配置,并尽量使用同一种路径形式。如果你在代码里面混合采用了多种配置形式,后期维护的成本会很高。
——————————————————我是重点分隔线———————————————————
(5)常见的注解类型:
我们既然知道了retrofit是通过注解将HTTP Api转化为java接口,那么我们就需要了解下都有哪些注解,该怎么用。下面先列举出常见的注解类型:
Path | GET | Query | QueryMap |
Patch | POST | Field | FieldMap |
Multipart | HTTP | Part | PartMap |
Streaming | PUT | Url | HEAD |
FormUrlEncoded | DELETE | Body | Header |
因为Retrofit注解内容比较多,所以具体实现放在下一篇Retrofit中进行专题讲解,有需要的读者可以关注一下。
(6)使用Retrofit后需要增加的混淆设置:
不输出警告
-dontwarn okio.**
-dontwarn javax.annotation.**
小结:本篇文章主要是Retrofit入门级讲解,先进入Retrofit的大门,了解相关的理论,并进行了一些简单的实现。通过这些基础内容,我们后续可以更好的掌握Retrofit的其他高级用法,比如Retrofit2.0和Retrofit+RxJava优雅实现网络请求等,当掌握了Retrofit的高级用法之后,就知道为什么现在网络框架首推Retrofit。
最后提一点:Retrofit1.0是一个 RESTful 的 HTTP 网络请求框架的封装,注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是 Retrofit 来完成的。Retrofit 2.0 开始内置 OkHttp,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作。再加上对于RxJava的支持,现在成为了首推的网络框架。