众所周知,目前市面上最流行的网络请求的方式莫过于Retrofit+OkHttp+RxJava.
首先我们要知道每个框架的作用:
Retrofit: Retrofit 仅负责 网络请求接口的封装
OkHttp:负责请求的过程
RxJava: 负责异步,各种线程之间的切换。
下面我们逐一介绍各个框架的使用,以及组合起来的使用:
一、Retrofit
流程图如下:
1、上图说明了如下几点:
- App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作。
- 在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用户的需求对结果进行解析。所以网络请求的本质仍旧是OkHttp完成的,retrofit只是帮使用者来进行工作简化的,比如配置网络,理数据等工作,提高这一系列操作的复用性。这也就是网上流行的一个不太准确的总结:okhttp是瑞士军刀,retrofit则是将这把瑞士军刀包装成了一个非常好用的指甲钳。
2、Retrofit 对Okhttp做了什么?
Retrofit并没有改变网络请求的本质,也无需改变,因为Okhttp已经足够强大,Retrofit的封装可以说是很强大,里面涉及到一堆的设计模式,可以通过注解直接配置请求,可以使用不同的http客户端,虽然默认是用http ,可以使用不同Json Converter 来序列化数据,同时提供对RxJava的支持,使用Retrofit + OkHttp + RxJava 可以说是目前比较
潮的一套框架,但是需要有比较高的门槛。
3、下面我们来看一下Retrofit的具体使用:
1、导入依赖: module/build.gradle下
dependencies {
// Retrofit库
compile 'com.squareup.retrofit2:retrofit:2.0.2'
// Okhttp库
compile 'com.squareup.okhttp3:okhttp:3.1.2'
}
2、添加网络权限:\src\main\AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
3、创建用于描述网络请求的接口
Retrofit将Http请求抽象成java接口:采用注解描述网络请求和配置网络请求参数。
1.用动态代理 动态 将该接口的注解“翻译”成一个 Http 请求,最后再执行 Http 请求
2.接口中的每个方法的参数都需要使用注解标注,否则会报错
注解类型:
2.1.网络请求方法:@GET 、@POST 、@PUT、 @DELETE、 @PATH 、@HEAD 、@OPTIONS 、@HTTP
2.2.标记类:@FormUrlEncoded、 @Multipart 、@Streaming
2.3.网络请求参数:@Header 、@hraders 、@URL、 @Body、 @Path 、@Field、 @FieldMap 、@Part 、@PartMap 、@Query 、@QueryMap
3.1、网络请求方法
@GET、@POST、@PUT、@DELETE、@HEAD
以上方法分别对应 HTTP中的网络请求方式:Retrofit把网络请求的URL分成了两部分
第一部分:在网络请求接口的注解设置
@GET("openapi.do?name=jack&pwd=123456")
fun login() : Call<Reception>
//@GET注解的作用:采用Get方法发送网络请求
//getCall() = 接收网络请求数据的方法
//其中返回类型为Call<*>,*是接收数据的类(此类可以自定义)
第二部分:在创建Retrofit实例时通过.baseUrl()设置
Retrofit.Builder()
.baseUrl("https://guz.retroft.com/")
.addConverterFactory(GsonConverterFactory.create())//设置数据解析器
.build()
// 从上面看出:一个请求的URL可以通过 替换块 和 请求方法的参数 来进行动态的URL更新。
// 替换块是由 被{}包裹起来的字符串构成
// 即:Retrofit支持动态改变网络请求根目录
网络请求的完整Url = 在创建Retrofit实例时通过baseUrl设置 + 3网络请求接口的注解设置
@HTTP
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解及更多功能的拓展。
具体使用:通过属性method,path,hasBody进行设置。
/**
* method:网络请求的方法(区分大小写)
* path:网络请求地址路径
* hasBody:是否有请求体
*/
@HTTP(method = "GET", path = "blog/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);
// {id} 表示是一个变量
// method 的值 retrofit 不会做处理,所以要自行保证准确
3.2、标记
a. @FromUrlEncoded
发送form-encoded的数据,每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
b.@Multipart
发送form-encoded的数据(适用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值。
具体使用:
public interface GetRequest_Interface {
/**
*表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
}
// 具体使用
GetRequest_Interface service = retrofit.create(GetRequest_Interface.class);
// @FormUrlEncoded
Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
// @Multipart
RequestBody name = RequestBody.create(textType, "Carson");
RequestBody age = RequestBody.create(textType, "24");
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
3.3、网络请求参数
a. @Headers
作用:添加请求头 &添加不固定的请求头
//@Header
@GET("user")
Call<user> getUser(@Header("Authorization") String authorization)
// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()
b.@Body
作用:以 Post方式 传递 自定义数据类型 给服务器
特别注意:如果提交的是一个Map,那么作用相当于 @Field
不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:
FormBody.Builder builder = new FormBody.Builder();