一,阐述
Retrofit是一个网络请求的封装,底层使用的是OKhttp。它简化了网络请求过程中参数的配置,可以将json转换成你想要的实体类,也可以配合Rxjava使用,使用简介方便。
和其他网络框架不同的是,它采用了运行时注解的方式提供功能; 采用RESTful风格,它是一种架构的规范和约束、原则,符合这个规范的架构就是RESTful架构。
实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作, 服务端返回数据之后,OkHttp 再将原始的结果交给 Retrofit,Retrofit然后根据用户的需求,对结果进行解析
二,注解分类
Retrofit和其他网络框架不同,使用了注解。一共使用了3种注解:HTTP请求方法注解、标记类注解、参数类注解
1,HTTP请求方法注解:@POST() 、@GET()等等
2,标记类注解:
@FormUrlEncode、---》表单请求
@Streaming
@Multipart -->上传文件用
3,参数类注解:
3.1,@Filed:
post请求时用,一般配合@FormUrlEncode使用,组成键值对进行传递。
3.2,@Body:
可以用post方式将json字符串发送到服务器
3.3,@Part、@PartMap
@Part单文件上传,@PartMap多文件上传;配合@Multipart使用
3.4,@Query等等
三,Retrofit用到的设计模式:
1,建造者模式(.builder)
2,适配器模式(callAdapter)
3,动态代理 (.create()方法里面使用了动态代理)
4,策略模式
5,装饰模式
四,其他介绍
1添加依赖,
implementation'com.squareup.retrofit2:retrofit:2.2.0'
implementation'com.squareup.retrofit2:converter-gson:2.2.0'
2,Retrofit是square开源的网络请求库,底层是使用OKHttp封装的,网络请求速度很快.
3,各种请求注解
@Headers | 添加请求头 |
@Path | 替换路径 |
@Query | 替代参数值,通常是结合get请求的 |
@FormUrlEncoded | 用表单数据提交 |
@Field | 替换参数值,是结合post请求的 |
@Body | 可以用来提交 Json 数据或者上传文件 |
4,现在一般用post的请求比较多,(post相对安全,地址不会明文显示,post请求不会被缓存,post请求不会保留在浏览器历史记录中,post不能被搜藏为书签,get请求地址有限制),所以暂时不介绍get的用法,等闲下来再记录.
4.1,@GET
使用@Query单个参数 @QueryMap多个参数
4.2,@POST
使用@Field 单个参数 @FieldMap 多个参数 @Part 上传文件 @PartMap 上传多个文件
五,代码实现
(一)BaseUrl阐述
假设BaseUrl是http://apis.baidu.com/txapi/的前提下
1,使用 @GET("word/word")会追加到baseUrl :http://apis.baidu.com/txapi/的后面,
即变成:http://apis.baidu.com/txapi/world/world
2,使用@Query("num") String num,@Query("page")String page;分别对应键值的名称与值。会追加到http://apis.baidu.com/txapi/world/world的后面,
即变成:http://apis.baidu.com/txapi/world/world?num=10&page=1
3, @Headers("apikey:81bf9da930c7f9825a3c3383f1d8d766")是 在基础之上为 其添加响应头
4,如果想继续增加参数,只需要在方法参数追加这样的形式就OK了:@Query("page")String page
(二)获取后台数据,使用@FieldMap
1,地址
//需要注意的是baseUrl必须以”/”结尾,否则报异常java.lang.IllegalArgumentException: baseUrl must end in /: http://dev-uc.ipktv.com/youCS/youC20170216
public static String baseUri = "http://dev-uc.ipktv.com/youCS/youC20170216/";
2,RetrofitApi
public interface RetrofitApi {
// 若不添加@FormUrlEncoded,则报异常java.lang.IllegalArgumentException: @FieldMap parameters can only be used with form encoding. (parameter #1)
//ava.lang.IllegalArgumentException: Missing either @POST URL or @Url parameter.
@FormUrlEncoded
@POST("ReceiveRecord/receiveVideo")
Call<RetrofitEntity> getResult(@FieldMap Map<String, String> fields);
3,获取结果
public class CreateParams {
public static Map<String,String > params1(){
Map<String, String> hashMap = new HashMap<>();
hashMap.put("ahead_user_id", "1");
hashMap.put("family_server_id", "f0f644a0d8cc");
hashMap.put("file", Constant.ossUrl + FileUtils.getFileName("/storage/emulated/0/laobi/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4"));
hashMap.put("time_long", "666");
hashMap.put("filesize", FileUtils.getFileSize(FileUtils.getFileSize("/storage/emulated/0/laobi/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4")));
hashMap.put("make_time", "12345678912");
return hashMap;
}
private void sendRequestFromServer() {
//1,获取retrofit对象
Retrofit build = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create()) //添加Json转换器支持
.baseUrl(Constant.baseUri)
.build();
//2,获取RetrofitApi
RetrofitApi retrofitApi = build.create(RetrofitApi.class);
//3,通过RetrofitApi拿到Call对象
Call<RetrofitEntity> call = retrofitApi.getResult(CreateParams.params1());
//4,通过Call执行异步请求,获取数据
call.enqueue(new Callback<RetrofitEntity>() {
@Override
public void onResponse(Call<RetrofitEntity> call, Response<RetrofitEntity> response) {
if(response.isSuccessful())
Log.e("date", "onResponse: "+response.body().getResult_code()+",,,"+response.body().getError_msg());
}
@Override
public void onFailure(Call<RetrofitEntity> call, Throwable t) {
Log.e("date", "onFailure: "+t.getMessage() );
}
});
}
(三),上传文件,使用@Multipart
1,RetrofitApi
@Multipart
@POST("UploadServlet")
Call<ResponseBody> upload(@Part("description") RequestBody description,
@Part MultipartBody.Part file);
2,执行请求
//1,获取文件
File file = new File("/storage/emulated/0/laobi/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4");
//2,将文件封装到RequestBody中
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
//3,将requestFile封装到MultipartBody.Part中
MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("aFile", file.getName(), requestFile);
//4,字符串描述
String descriptionString = "This is a description";
//5,将字符串描述封装到RequestBody中
RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
//开启网络上传文件
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create()) //添加Json转换器支持
.baseUrl(Constant.baseUri)
.build()
.create(RetrofitApi.class)
.upload(description,multipartBody)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
(四),获取后台数据,post提交json数据,使用@Body
@POST("/tasks")
Call<UploadBean> getApple(@Body UploadBean bean);
UploadBean uploadBean = new UploadBean("小毕先生", 100000000);
//开启网络上传文件
new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create()) //添加Json转换器支持
.baseUrl(Constant.baseUri)
.build()
.create(RetrofitApi.class)
.getApple(uploadBean)
.enqueue(new Callback<UploadBean>() {
@Override
public void onResponse(Call<UploadBean> call, Response<UploadBean> response) {
}
@Override
public void onFailure(Call<UploadBean> call, Throwable t) {
}
});
优秀文章: