Android之网络请求9————Retrofit的简单使用
Android之网络请求8————Retrofit的简单使用
文章目录
- Android之网络请求8————Retrofit的简单使用
- 一.Retrofit的介绍
- 二.Retrofit的简单使用
- 三.Retrofit的注解
- 1.概述
- 2.网络请求方法
- 3.标记类
- 4.网络请求参数
- 四.Retrofit的数据解析器和网络请求适配器
- 1.数据解析器
- 2.网络请求适配器
- 五.Retrofit和GSON
- 1.步骤a:添加Retrofit库的依赖
- 2.步骤b:创建 接收服务器返回数据 的类
- 3.步骤c:创建 用于描述网络请求 的接口
- 4.步骤d:进行网络请求
- 5.运行结果
- 六.Retrofit和Rxjava的结合
- 1.步骤a:添加Retrofit库的依赖
- 2.步骤b:创建 接收服务器返回数据 的类
- 3.步骤c:创建 用于描述网络请求 的接口
- 4.步骤d:进行网络请求
- 5.运行结果
- 七.参考资料
- 八.文章索引
一.Retrofit的介绍
Retreofit是什么,根据其官方文档的介绍,他就是一个适用于 Android 和 Java 的类型安全的 HTTP 客户端。特别说明Retrofit网络请求本质是有OkHttp完成的,而Retrofit仅负责网络请求接口的封装。
图片来源网上:

二.Retrofit的简单使用
Retrofit的简单使用我们先从请求百度URL开始
步骤1:
添加第三方库依赖
compile 'com.squareup.retrofit2:retrofit:2.4.0'compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
步骤2:
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
步骤3:
创建用于描述请求的接口
public interface BaiduInterface {//@GET指定请求方法,@GETCall<String> baidu(@Url String url);
}
步骤4:
进行请求
//a.创建Retrofit对象Retrofit retrofit = new Retrofit.Builder()//指定baseurl,这里有坑,最后后缀出带着“/”.baseUrl("http://www.baidu.com/")//设置内容格式,这种对应的数据返回值是String类型.addConverterFactory(ScalarsConverterFactory.create())//定义client类型.client(new OkHttpClient())//创建.build();//b,获得定义的接口的实例BaiduInterface baiduInterface = retrofit.create(BaiduInterface.class);//配置参数Call<String> baidu = baiduInterface.baidu("http://www.baidu.com");//c.执行异步请求baidu.enqueue(new Callback<String>() {@Overridepublic void onResponse(Call<String> call, Response<String> response) {Log.d("1111", "onResponse: "+response.body());}@Overridepublic void onFailure(Call<String> call, Throwable t) {Log.d("1111", "onResponse: "+t);}});
请求结果:
三.Retrofit的注解
上面我们简单使用了Retrofit请求了百度的。对Retrofit的使用有了简单的了解,在上面的代码中,出现了@GET和@URL,可以看出Retrofit大量使用了注解,对请求进行了封装,我们继续来看Retrofit中使用的注解。
1.概述
在Retrofit中,注解的使用都在定义的接口中,分为3类:即网络请求方法,标记类,网络请求参数。

2.网络请求方法
网络请求方法如下:

可以看出来这些都是Http的方法,我们一般常用的就是GET和POST
具体说明:
a. @GET、@POST、@PUT、@DELETE、@HEAD
以上方法分别对应 HTTP中的网络请求方式
每个注解后面都可以设置一个URL,也可以不设置
public interface RetrofitInterface {@GET("https://www.baidu.com")Call<String> baidu();//@GE作用:采用Get方法发送请求//Call String是请求返回数据的格式,可以是String,也可以是json,也可是GSON。 //baidu() 即进行请求的方法//关于URL部分,在下面有教详细的讲解
}
b.@HTTP
作用:替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
public interface RetrofitInterface {/*** method:网络请求的方法(区分大小写)* path:网络请求地址路径* hasBody:是否有请求体*/@HTTP(method = "GET", path ="https://www.baidu.com", hasBody = false)Call<ResponseBody> getCall(@Path("id") int id);// method 的值 retrofit 不会做处理,所以要自行保证准确
}
c.关于URL
Retrofit将URL分为两部分,一部分在请求接口的注解后,一部分在Retrofit的baseUrl中。即
// 第1部分:在网络请求接口的注解设置@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
Call<Translation> getCall();// 第2部分:在创建Retrofit实例时通过.baseUrl()设置
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://fanyi.youdao.com/") //设置网络请求的Url地址.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器.build();
网络请求的完整 Url =在创建Retrofit实例时通过.baseUrl()设置 +网络请求接口的注解设置(下面称 “path“ )
具体整合规则

path的URL还可以使用替换块
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
同时网络请求参数@URL也可以设置URL
public interface RetrofitInterface {@GETCall<String> baidu(@Url String url);
}
3.标记类

a.FormUrlEncoded
- 作用:表示发送form-encoded的数据
- 注意:每个键值对都需要用@Filed来注解键名,随后的对象需要提供值。
定义接口方法
public interface RetrofitInterface {/***表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)* Field("username") 表示将后面的 String name 中name的取值作为 username 的值*/@POST("/form")@FormUrlEncodedCall<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);}
b.Multipart
- 作用:表示发送form-encoded的数据(适用于 有文件 上传的场景)
- 注意:每个键值对都需要用@part来注解键名,随后对象需要提供值
public interface RetrofitInterface {/*** {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型* 除 {@link okhttp3.MultipartBody.Part} 以外,* 其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),*/@POST("/form")@MultipartCall<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
}
c.@Streaming
- 作用:表示返回的数据以流的形式返回,场用于大文件传输的场景
- 注意:url由于是可变的,因此用 @URL 注解符号来进行指定,大文件官方建议用 @Streaming 来进行注解,不然会出现IO异常,小文件可以忽略不注入。如果想进行断点续传的话 可以在此加入header
public interface ApiService {@Streaming@GETObservable<ResponseBody> downloadFile(@Url String fileUrl);
}
4.网络请求参数

a.@Header & @Headers
- 作用:添加请求头
具体使用:
// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()// 以上的效果是一致的。
// 区别在于使用场景和使用方式
// 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
// 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法
b.@Body
- 作用:以Post方式传递自定义数据类型给服务器
- 注意: 如果提交的是一个Map,那么作用相当于@Field,不过Map要经过FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:
FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");
c.Field&FieldMap
- 作用:发送 Post请求 时提交请求的表单字段
- 注意:与 @FormUrlEncoded 注解配合使用
Field的使用
public interface RetrofitInterface {/***表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)* Field("username") 表示将后面的 String name 中name的取值作为 username 的值*/@POST("/form")@FormUrlEncodedCall<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
}//具体使用Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
FieldMap的使用
public interface RetrofitInterface {/***表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)* Field("username") 表示将后面的 String name 中name的取值作为 username 的值*/@POST("/form")@FormUrlEncodedCall<ResponseBody>testFormUrlEncoded2(@FieldMap Map<String, Object> map);
}//具体使用Map<String, Object> map = new HashMap<>();map.put("username", "Carson");map.put("age", 24);Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
d.@Part & @PartMap
- 作用:发送的Post请求时提交的表单字段
- 注意:与 @Multipart 注解配合使用
- 与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景
@Part的使用
public interface RetrofitInterface {/*** {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),*/@POST("/form")@MultipartCall<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
}MediaType textType = MediaType.parse("text/plain");RequestBody name = RequestBody.create(textType, "Carson");RequestBody age = RequestBody.create(textType, "24");RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");
//调用MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);ResponseBodyPrinter.printResponseBody(call3);
@PartMap的使用
public interface RetrofitInterface {/*** PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,* 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}* 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用 @Part MultipartBody.Part */@POST("/form")@MultipartCall<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
}MediaType textType = MediaType.parse("text/plain");RequestBody name = RequestBody.create(textType, "Carson");RequestBody age = RequestBody.create(textType, "24");RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");
//调用Map<String, RequestBody> fileUpload2Args = new HashMap<>();fileUpload2Args.put("name", name);fileUpload2Args.put("age", age);//这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有//fileUpload2Args.put("file", file);Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件ResponseBodyPrinter.printResponseBody(call4);
e.@Query和@QueryMap
- 作用:用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
- 使用:和上面的两个相同
f. @Path
- 作用:URL的省缺值
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
g.@Url
- 作用:直接传入一个请求的URL变量
- 具体使用
public interface RetrofitInterface {@GETCall<String> baidu(@Url String url);
}
四.Retrofit的数据解析器和网络请求适配器
在上面的请求百度的例子中,我们使用了ScalarsConverterFactory.create()作为数据的解析器,同时Retrofit也支持多种网络请求适配器方式,比如:guava、Java8和rxjava
数据解析器和网络请求的适配器的添加发生在创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台.build();
1.数据解析器
Retrofit支持多种数据解析器,如下:
| 数据解析器 | Gradle依赖 |
|---|---|
| Gson | com.squareup.retrofit2:converter-gson:2.0.2 |
| Jackson | com.squareup.retrofit2:converter-jackson:2.0.2 |
| Simple XML | com.squareup.retrofit2:converter-simplexml:2.0.2 |
| Protobuf | com.squareup.retrofit2:converter-protobuf:2.0.2 |
| Moshi | com.squareup.retrofit2:converter-moshi:2.0.2 |
| Wire | com.squareup.retrofit2:converter-wire:2.0.2 |
| Scalars | com.squareup.retrofit2:converter-scalars:2.0.2 |
2.网络请求适配器
Retrofit支持多种网络请求适配器方式:guava、Java8和rxjava.
使用时如使用的是 Android 默认的 CallAdapter,则不需要添加网络请求适配器的依赖
需要在Gradle添加依赖:
| 网络请求适配器 | Gradle依赖 |
|---|---|
| guava | com.squareup.retrofit2:adapter-guava:2.0.2 |
| Java8 | com.squareup.retrofit2:adapter-java8:2.0.2 |
| rxjava | com.squareup.retrofit2:adapter-rxjava:2.0.2 |
五.Retrofit和GSON
以豆瓣电影上映接口的请求为例:
API接口
请求URL:
返回的JSON数据(详细内容可查看链接):
具体实现:
1.步骤a:添加Retrofit库的依赖
添加Retrofit和GSON的依赖
compile 'com.squareup.retrofit2:retrofit:2.4.0'compile 'com.squareup.retrofit2:converter-gson:2.4.0'
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
2.步骤b:创建 接收服务器返回数据 的类
这里只接收了部分数据
public class Theaters {private int count; //返回数量private int start; //分页量private int total; //数据库总数量@SerializedName("subjects")private List<Subjects> data; //电影的具体信息private class Subjects {private String title;//电影名private String mainland_pubdate;//大陆上映时间private String alt;//网页连接}//定义 输出返回数据 的方法public void show() {Log.d("返回数量", ""+count);Log.d("分页量", ""+start);Log.d("数据库总数量", ""+total);for (Subjects subjects: data){Log.d("电影名", ""+subjects.title);Log.d("大陆上映时间", ""+subjects.mainland_pubdate);Log.d("网页连接", ""+subjects.alt);}}
}
3.步骤c:创建 用于描述网络请求 的接口
public interface RetrofitInterface {@GET("in_theaters")Call<Theaters> theaters(@QueryMap Map<String ,Object>map);
}
4.步骤d:进行网络请求
//a.创建Retrofit对象Retrofit retrofit = new Retrofit.Builder()//指定baseurl,这里有坑,最后后缀出带着“/”.baseUrl("https://api.douban.com/v2/movie/")//设置内容格式,这种对应的数据返回值是String类型.addConverterFactory(GsonConverterFactory.create())//创建.build();//b,获得定义的接口的实例RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);// 实现的效果与上面相同,但要传入MapMap<String, Object> map = new HashMap<>();map.put("apikey", "0b2bdeda43b5688921839c8ecb20399b");map.put("start",0);map.put("count", 100);//配置参数Call<Theaters> call = retrofitInterface.theaters(map);//c.进行网络请求call.enqueue(new Callback<Theaters>() {//请求成功时回调@Overridepublic void onResponse(Call<Theaters> call, Response<Theaters> response) {// 处理返回的数据结果response.body().show();}//请求失败时回调@Overridepublic void onFailure(Call<Theaters> call, Throwable throwable) {Log.e("retrofit", "onFailure: "+throwable);}});
5.运行结果
六.Retrofit和Rxjava的结合
还是以上面的接口为例:关于Rxjava更多详细的内容可以参看我之前的博客Android之Rxjava2.X 1————Rxjava概述
API接口同上
1.步骤a:添加Retrofit库的依赖
添加Retrofit和GSON的依赖
// Android 支持 Rxjava// 此处一定要注意使用RxJava2的版本compile 'io.reactivex.rxjava2:rxjava:2.1.7'compile 'io.reactivex.rxjava2:rxandroid:2.0.1'// Android 支持 Retrofitcompile 'com.squareup.retrofit2:retrofit:2.4.0'// 衔接 Retrofit & RxJava// 此处一定要注意使用RxJava2的版本compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'// 支持Gson解析compile 'com.squareup.retrofit2:converter-gson:2.4.0'
添加权限
<uses-permission android:name="android.permission.INTERNET"/>
2.步骤b:创建 接收服务器返回数据 的类
这里只接收了部分数据
public class Theaters {private int count; //返回数量private int start; //分页量private int total; //数据库总数量@SerializedName("subjects")private List<Subjects> data; //电影的具体信息private class Subjects {private String title;//电影名private String mainland_pubdate;//大陆上映时间private String alt;//网页连接}//定义 输出返回数据 的方法public void show() {Log.d("返回数量", ""+count);Log.d("分页量", ""+start);Log.d("数据库总数量", ""+total);for (Subjects subjects: data){Log.d("电影名", ""+subjects.title);Log.d("大陆上映时间", ""+subjects.mainland_pubdate);Log.d("网页连接", ""+subjects.alt);}}
}
3.步骤c:创建 用于描述网络请求 的接口
public interface RetrofitInterface {@GET("in_theaters")Observable<Theaters> theaters2(@QueryMap Map<String ,Object>map);
}
4.步骤d:进行网络请求
//a.创建Retrofit对象Retrofit retrofit = new Retrofit.Builder()//指定baseurl,这里有坑,最后后缀出带着“/”.baseUrl("https://api.douban.com/v2/movie/")//设置内容格式,这种对应的数据返回值是String类型.addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava//创建.build();//b,获得定义的接口的实例RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);// 实现的效果与上面相同,但要传入MapMap<String, Object> map = new HashMap<>();map.put("apikey", "0b2bdeda43b5688921839c8ecb20399b");map.put("start", 0);map.put("count", 100);//配置参数Observable<Theaters> observable = retrofitInterface.theaters2(map);//c. 通过Rxjava进行网络请求observable.subscribeOn(Schedulers.io()) // 切换到IO线程进行网络请求.observeOn(AndroidSchedulers.mainThread()) // 切换回到主线程 处理请求结果.subscribe(new Observer<Theaters>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Theaters result) { // e.接收服务器返回的数据result.show();}@Overridepublic void onError(Throwable e) {Log.d("Retrofit", "请求失败");}@Overridepublic void onComplete() {}});
5.运行结果
https://www.jianshu.com/p/0fda3132cf98
七.参考资料
这是一份很详细的 Retrofit 2.0 使用教程
网络加载框架 - Retrofit
Retrofit 官方文档翻译
八.文章索引
Android之网络请求1————HTTP协议
Android之网络请求2————OkHttp的基本使用
Android之网络请求3————OkHttp的拦截器和封装
Android之网络请求4————OkHttp源码1:框架
Android之网络请求5————OkHttp源码2:发送请求
Android之网络请求6————OkHttp源码3:拦截器链
Android之网络请求7————OkHttp源码4:网络操作
Android之网络请求8————OkHttp源码5:缓存相关
Android之网络请求9————Retrofit的简单使用
Android之网络请求10————Retrofit的进阶使用
Android之网络请求11————Retrofit的源码分析
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
