(源码教程): https://www.jianshu.com/p/0c055ad46b6c

正文

Retrofit简介
        Rrotrofit是一个RESTful架构的HTTP网络请求框架的封装。网络请求工作,本质上是 Okhttp 完成的,Retrofit 仅负责网络请求接口的封装。Retrofit接口层封装了requestParams、Header、Url 等信息,后续的请求工作由OkHttp来完成。服务端返回数据后,OkHttp将返回结果交给Retrofit,Retrofit根据用户的需求对结果进行解析。
public interface GetRequest_Interface {@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json")Call<Translation>  getCall();// @GET注解的作用:采用Get方法发送网络请求// getCall() = 接收网络请求数据的方法// 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
}
Retrofit与其他框架的对比
Retrofit中URL组成
Url 由 BaseUrl 和 path组成。BaseUrl在 Rotrofit 实例化时进行设置。path在接口描述中设置。
Url =  “ http://host:port/aaa/pathname ”;
BaseUrl = “ http://host:port/aaa/ ”;
path =  “pathname ”;
Retrofit注解类型
1.注解网络请求方法
2.注解---标记类
3.注解---网络请求参数
Retrofit注解详解
1.请求方法---注解
1.1@HTTP注解的作用
@HTTP注解可以替换@GET、@POST、@PUT、@DELETE、@HEAD注解,及更多功能扩展。
public interface GetRequest_Interface {/*** method:网络请求的方法(区分大小写)* path:网络请求地址路径* hasBody:是否有请求体*/@HTTP(method = "GET", path = "blog/{id}", hasBody = false)Call<ResponseBody> getCall(@Path("id") int id);// {id} 表示是一个变量// method的值,retrofit不会做检查处理,所以要自行保证准确
}
2.标记类---注解
2.1 @FormUrlEncode
@FormUrlEncode 表示请求体是一个Form表单,需要用 @Filed 来注解每个键值对的键名称,随后的对象需要提供键值对的 值。它用于Post请求,不能用于Get请求,因为Get请求中没有请求体。
public interface GetRequest_Interface {/*** @FormUrlEncoded表明是一个表单格式的请求(application/x-www-form-urlencoded)* Field("username") 表示将后面的String name 中name的取值作为 username 的值*/@POST("/form")@FormUrlEncodedCall<ResponseBody> testFormUrlEncoded(@Field("username") String name,@Field("age") int age);
}//具体使用
GetRequest_Interface service = retrofit.create(GetRequest_Interface.class);
Call<ResponseBody> call1 = service.testFormUrlEncoded("Carson", 24);

2.2@Multipart

@Multipart表示请求体是一个文件上传的Form表单,需要用@Part来注解每个键值对的键名称,随后的对象需要提供键值对的值。
public interface GetRequest_Interface {/*** @Part后面支持三种类型:RequestBody、okhttp3.MultipartBody.Part、任意类型;* 除了okhttp3.MultipartBody.Part类型以外,其它类型都必须带上表单字段,* okhttp3.MultipartBody.Part中已经包含了表单字段的信息。*/@POST("/form")@MultipartCall<ResponseBody> testFileUpload(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
}// 具体使用
GetRequest_Interface mService = retrofit.create(GetRequest_Interface.class);
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 = mService.testFileUpload(name, age, filePart);
3.网络请求参数---注解
3.1 @Headers
@Headers 用于在描述接口中 静态添加请求头
public interface GetRequest_Interface {@Headers("Authorization: authorization”,"Accept: application/vnd.yourapi.v1.full+json","User-Agent: Your-App-Name")@GET("user")Call<User> getUser()
}
3.2  @Header
@Header 用于动 态添加请求头 ,即需要添加的请求头,会作为参数传入
public interface GetRequest_Interface {@GET("user")Call<User> getUser(@Header("Authorization") String authorization)
}
3.3 @Body
@Body用于非表单请求体, 并以Post方式提交自定义的数据类型 。但是如果提交的是一个Map集合,那么@Body的作用就相当于@Field,不过此时的map需要被FormBody.Builder处理成符合Okhttp的表单。
public interface GetRequest_Interface {@FormUrlEncoded@POST("book/reviews")Call<String> addReviews(@Body Reviews reviews);
}public class Reviews {public String book;public String title;public String content;public String rating;
}//具体使用
Reviews reviews = new Reviews();
reviews.setBook(“百科全书”);
reviews.setTitle(“标题”);
reviews.setContent(“描述内容”);
reviews.setRating(“hello!”);
Call<ResponseBody> call = service.addReviews(reviews);//Map处理过程
FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");
3.4 @Field & @FieldMap
@Field和FieldMap与标记类@FormUrlEncode配合使用,作为发送Post请求时提交请求参数的表单字段。
public interface GetRequest_Interface {/*** 表明是一个表单格式的请求(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);/*** Map的key作为表单的键*/@POST("/form")@FormUrlEncodedCall<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);
}//具体使用
// @Field
Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
// @FieldMap
// 实现的效果与上面相同,但要传入Map
Map<String, Object> map = new HashMap<>();
map.put("username", "Carson");
map.put("age", 24);
Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
3.5 @Part & @PartMap
@Part和@PartMap与标记类@Multipart配合使用, 作为发送Post请求时提交请求参数的表单字段。适用于文件上传的场景。
public interface GetRequest_Interface {/*** @Part后面支持三种类型:RequestBody、 okhttp3.MultipartBody.Part、任意类型:* 除了okhttp3.MultipartBody.Part以外,其它类型都必须带上表单字段,* okhttp3.MultipartBody.Part中已经包含了表单字段的信息。*/@POST("/form")@MultipartCall<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age,@Part MultipartBody.Part file);/*** PartMap 注解支持一个Map作为参数,支持RequestBody类型,* 如果有其它的类型,会被retrofit2.Converter转换,如后面会介绍的,* 使用com.google.gson.Gson的retrofit2.converter.gson.GsonRequestBodyConverter* 所以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"), "这里是模拟文件的内容");
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);// @Part
Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
ResponseBodyPrinter.printResponseBody(call3);// @PartMap
// 实现和上面同样的效果
Map<String, RequestBody> fileUpload2Args = new HashMap<>();
fileUpload2Args.put("name", name);
fileUpload2Args.put("age", age);
Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart);
// 单独处理文件
ResponseBodyPrinter.printResponseBody(call4);
3.6 @Query & @QueryMap
@Query和@QueryMap用于@Get方法的查询参数 (Query = Url中?后面的 key-value)
public interface GetRequest_Interface {@GET("book/search")    Call<ResponseBody> cate1(@Query("username") String username,@Query(“age”) int age);@GET("book/search")Call<ResponseBody> cate2(@QueryMap Map<String, Object> map);Call<ResponseBody> cate3(@Query("list") List<String> strList,);
}//具体使用
// @Query
Call<ResponseBody> call1 = service.cate1("Carson",19);
// @QueryMap
// 实现的效果与上面相同,但要传入Map
Map<String, Object> map = new HashMap<>();
map.put("username", "Carson");
map.put("age", 24);
Call<ResponseBody> call2 = service.cate2(map);
3.7 @Path
@Path 用作Url地址的缺省值。Post、Get、Put、Delete中都可以使用
public interface GetRequest_Interface {@GET("users/{user}/repos")Call<ResponseBody> getBlog(@Path("user") String user );// 访问的API是:https://api.github.com/users/{user}/repos// 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
}//具体使用
Call<ResponseBody> call = service.getBlog(“carson”);
//则描述的接口为:“users/carson/repos”。
3.8 @Url
@Url 用于在网络请求的时候,直接传入一个请求的Url变量,用于Url设置。
public interface GetRequest_Interface {@GETCall<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);// 当@HTTP、@POST、@GET中设置了path时,@GET传入的URL就可以省略// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
}//具体使用
Url url = “http://www.baidu.com/abc”
Call<ResponseBody> call = service.testUrlAndQuery(url, true);
//则描述的接口为:“http://www.baidu.com/abc?showAll=true”。

自定义Interceptor拦截器

创建一个自定义的Interceptor拦截器,然后在创建Retrofit实例的地方通过addInterceptor()进行添加,通过它我们可以实现一些拦截的操作,比如下面:我们想要拦截每一次请求,添加一个公共的请求参数。
//自定义拦截器——添加公共参数
public class CustomInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();HttpUrl httpUrl = request.url().newBuilder().addQueryParameter("token", "tokenValue").build();request = request.newBuilder().url(httpUrl).build();return chain.proceed(request);}
}//自定义拦截器—添加 header
//添加header参数Request提供了两个方法,一个是header(key, value),
//另一个是.addHeader(key, value),两者的区别是,header()如果有重名的将会覆盖,
//而addHeader()允许相同key值的header存在
public class RequestInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {Request original = chain.request();Request request = original.newBuilder().header("User-Agent", "Your-App-Name").header("Accept", "application/vnd.yourapi.v1.full+json").method(original.method(), original.body()).build();return chain.proceed(request);}
}//添加拦截器Interceptor
private static OkHttpClient getNewClient(){return new OkHttpClient.Builder().addInterceptor(new CustomInterceptor()).addInterceptor(new RequestInterceptor()).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).build();
}
Retrofit官方提供了一个方便查看日志的Interceptor拦截器,方便的控制打印信息的类型。HttpLoggingInterceptor提供4种控制打印信息类型的等级,分别是:NONE、BASIC、HEADERS、BODY。
//引入依赖
implement 'com.squareup.okhttp3:logging-interceptor:3.4.1’
//具体使用
private static OkHttpClient getNewClient(){HttpLoggingInterceptor logging = new HttpLoggingInterceptor();logging.setLevel(HttpLoggingInterceptor.Level.BODY);return new OkHttpClient.Builder().addInterceptor(logging).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).build();
}

Retrofit解析器与适配器

1.数据解析器 Converter,Retrofit支持多种解析器
2.网络请求适配器 CallAdapter,Retrofit支持多种网络请求适配器

Retrofit中的API

Call<ResponseBody> call = servers.lookBookDetail(“参数”);
call.enqueue(new Callback<Translation>() {//请求成功时回调@Overridepublic void onResponse(Call<Translation> call, Response<Translation> response) {// 对返回数据进行处理response.body().show();}//请求失败时候的回调@Overridepublic void onFailure(Call<Translation> call, Throwable throwable) {System.out.println("连接失败");}
});
1.异步请求
   call.enqueue();
2.同步请求
   call.execute();
3.取消请求
call.cancel();
4.对数据进行处理
   respose.body().show();

Retrofit的使用

1.在app模块的build.gradle文件中引入Retrofit框架。
implement 'com.squareup.retrofit2:retrofit:2.0.2’
implement 'com.squareup.retrofit2:converter-gson:2.0.2'

2.自定义数据接收实体类
3.创建用于描述网络请求的接口
4.创建Retrofit对象
5.创建网络请求接口实例
6.发送网络请求
7.处理返回数据、
//创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder().baseUrl(""http://fanyi.youdao.com/"").addConverterFactory(ProtoConverterFactory.create()) // 支持Prototocobuff解析.addConverterFactory(GsonConverterFactory.create()) // 支持Gson解析.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava.build();
//创建 网络请求接口 的实例
PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);
//对网络请求进行封装
Call<Translation1> call = request.getCall("I love you”);
//发送网络请求(异步)
call.enqueue(new Callback<Translation1>() {
//请求成功时回调@Overridepublic void onResponse(Call<Translation1> call, Response<Translation1> response) {// 步骤7:处理返回的数据结果:输出翻译的内容  System.out.println(response.body().getTranslateResult().get(0).get(0).getTgt());}//请求失败时回调@Overridepublic void onFailure(Call<Translation1> call, Throwable throwable) {System.out.println("请求失败");System.out.println(throwable.getMessage());}
});

Retrofit实现文件上传

public interface FileUploadService {  // 上传单个文件@Multipart@POST("upload")Call<ResponseBody> uploadFile(@Part("description") RequestBody description,@Part MultipartBody.Part file);// 上传多个文件@Multipart@POST("upload")Call<ResponseBody> uploadMultipleFiles(@Part("description") RequestBody description,@Part MultipartBody.Part file1,@Part MultipartBody.Part file2);
}
//Retrofit上传文件的工具类
public class retrofitFileUtil{public static final String MULTIPART_FORM_DATA = "multipart/form-data”;private RequestBody createPartFromString(String descriptionString) {  return RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), descriptionString);}private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {  File file = FileUtils.getFile(this, fileUri);// 为file建立RequestBody实例RequestBody rf = RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);// MultipartBody.Part借助文件名完成最终的上传return MultipartBody.Part.createFormData(partName, file.getName(), rf);}
}
Uri file1Uri = ... // 从文件选择器或者摄像头中获取
Uri file2Uri = …// 创建上传的service实例
FileUploadService service = ServiceGenerator.createService(FileUploadService.class);
// 创建文件的part (photo, video, ...)
MultipartBody.Part body1 = prepareFilePart("video", file1Uri);
MultipartBody.Part body2 = prepareFilePart("thumbnail", file2Uri);
// 添加其他的part
RequestBody description = createPartFromString("hello, this is description speaking");
// 最后执行异步请求操作
Call<ResponseBody> call = service.uploadMultipleFiles(description, body1, body2);
call.enqueue(new Callback<ResponseBody>() {  @Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {Log.v("Upload", "success");}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {Log.e("Upload error:", t.getMessage());}
});

Retrofit教程相关推荐

  1. Android 精华 - 收藏全集 -

    Android - 收藏集 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发 ...

  2. Android开发之第三方框架使用汇总

    1. image loading 框架: 1.1 Glide1.2 Picasso1.3 后续更新... 2.网络框架: 2.1 xUtil32.2 OkHttp32.3 Retrofit2.4 后续 ...

  3. Android进阶-第三方框架使用汇总

    image loading 框架: 1.1 Glide1.2 Picasso1.3 后续更新... 2.网络框架: 2.1 xUtil32.2 OkHttp32.3 Retrofit2.4 后续更新. ...

  4. 掘金 Android 文章精选合集

    掘金官方 2017.07.10 16:42* 字数 175276 阅读 46638 评论 12 喜欢 653 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有 ...

  5. Retrofit 2简单使用教程

    作者: Chike Mgbemena 原文地址:https://code.tutsplus.com/tutorials/getting-started-with-retrofit-2–cms-2779 ...

  6. Retrofit的使用教程(一)

    这篇教程基于retrofit1.9版本和android平台. 以下部分代码和教程参考自http://square.github.io/retrofit/ 准备: retrofit的下载地址:https ...

  7. Retrofit 2.0 使用教程

    前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将献上一份非常详细Retrofit v2.0的使用教程,希望你们会 ...

  8. 详细的 Retrofit 2.0 使用教程

    这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解) 前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天, ...

  9. Android Retrofit使用教程(三):Retrofit与RxJava初相逢

    上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用. 了解RxJava RxJava有种种好处,我不在这里一一讲述.这里我只给 ...

最新文章

  1. [再读书]私有构造函数
  2. Security issue about static code checking
  3. linux vscode配置spring boot开发环境
  4. .NET的一点历史故事:招兵买马和聚义山林
  5. 《操作系统真象还原》-阅读笔记(下)
  6. zabbix中mysql连不上的排错_zabbix监控软件的使用排错
  7. php each函数二维数组,PHP特定函数foreach遍历一二维数组
  8. console.log(12.toString())为啥会报错呢?
  9. 20200519每日一句
  10. cxonev4验证用户_欧姆龙plc编程软件下载 omron plc编程软件(CX-ONE) v4.31 中文免费版(附序列号+安装教程) 下载-脚本之家...
  11. 2020年mac上最值得使用的五大录屏软件
  12. matlab xlsread 日期,为什么Xlsread读取(日期时间)为字符串
  13. Java web之五-网站访问统计
  14. 程序员夏天穿格子衫,那么冬天穿什么?答案扎心了
  15. 各种逆元求法 组合数取模 comb (组合数 Lucas)
  16. 12031,终结你!
  17. “AI+教育”假套路还是真功夫,本质还是对AI能力的拷问
  18. 星巴克REST案例分析(转载自InfoQ)
  19. SpringBoot参数校验--List类型
  20. SQL高级语法学习总结(一)

热门文章

  1. Linux系统的常见命令记忆【Ubuntu】
  2. YOLOv5的Tricks | 【Trick13】YOLOv5的detect.py脚本的解析与简化
  3. php无限级分类是什么意思,PHP 无限级分类(递归)
  4. 聚类分析:使用过程CLUSTER实现层次法(聚多少类的评判)
  5. 集合的运算(C++单链表实现)
  6. 《离散数学》1 集合及其运算
  7. mpvue微信小程序中使用svg图标,并通过代码动态改变图标颜色
  8. cin和cout的使用
  9. 贝壳找房值百亿美元吗?
  10. matlab解比例导引法方程,[转载]比例导引法在三维制导中应用的程序详解与过程图解...