概述

Retrofit是当下最热门的Android网络请求库,准确的来说Retrofit是一个RESTful的HTTP网络请求框架的封装,因为它内部网络请求的工作,本质上是通过OkHttp完成,而Retrofit仅负责网络请求接口的封装。具体是客户端通过Retrofit请求网络,实际上是通过Retrofit的接口层封装了请求参数,header,url等信息,之后由OkHttp完成后续的请求工作。然后在服务端返回数据之后,OkHttp将原始的结果传递给Retrofit,Retrofit根据客户端的相关配置,将结果进行解析回调给客户端

基本使用

一、Get请求

Retrofit在使用的过程中需要定义接口层,接口层中的每个方法标识一个独立的请求,如下定义接口层ApiService

public interface ApiService {@GET("users/list")Call<List<User>> getUsers();
}

@Get注解作用于方法之上,表明这是一个Get请求,@Get注解的value值与Retrofit中配置的baseUrl组成完整的请求url,List<User>代表响应结果类型,下面通过Retrofit请求完成上述请求

        // builder模式构建Retrofit对象Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();// 创建接口层的代理对象,内部通过动态代理创建了ApiService的代理对象  ApiService api = retrofit.create(ApiService.class);// 执行异步请求api.getUsers().enqueue(new Callback<List<User>>() {@Overridepublic void onResponse(Call<List<User>> call, Response<List<User>> response) {// 处理结果}@Overridepublic void onFailure(Call<List<User>> call, Throwable t) {// 处理异常}});

我们知道原始的请求响应结果其实是ResponseBody,那么我们这里声明了响应数据类型为List<User>,Retrofit内部是如何实现的呢?其实是通过我们构建Retrofit时传入的转换器GsonConverterFactory完成一个响应结果的转换

二、动态url访问@PATH

比如我现在要访问类似这样的url https://api.example.com/user/1 那么接口层定义如下:

public interface ApiService {@GET("user/{id}")Call<User> getUser(@Path("id") String id);
}

@Get注解中使用了{id}作为占位符,实际运行会通过方法中@Path(“id”)注解标注的参数进行替换,访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);api.getUser("1").enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {}@Overridepublic void onFailure(Call<User> call, Throwable t) {}});

三、带有查询参数设置@Query的Get请求

例如我们要访问这样的url https://api.example.com/users?username=zhangsan 接口层定义如下:

public interface ApiService {@GET("users")Call<User> getUserByUserName(@Query("username") String username);
}

通过@Get表明了请求方式,通过@Query标注了请求的参数名,同样的也适用与Post请求,只需要将@Get注解替换为@Post即可,访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);api.getUserByUserName("zhangsan").enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {}@Overridepublic void onFailure(Call<User> call, Throwable t) {}});

四、POST请求体的方式向服务器传入json字符串@Body

在平时与服务端的接口交互中,我们一般会将请求参数直接封装成一个json字符串传递给服务端,通过Retrofit如何实现呢?接口层定义如下:

public interface ApiService {@POST("users/add")Call<List<User>> addUser(@Body User user);
}

可以看到我们通过@Body注解标注参数对象即可,而后Retrofit内部将User对象转换了json字符串传递给服务端,访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);User user = new User("zhangsan",24,"zhangsan@163.com")api.addUser(user).enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<List<User>> call, Response<User> response) {}@Overridepublic void onFailure(Call<List<User>> call, Throwable t) {}});

Retrofit默认只能接受@Body的RequestBody类型,那么我们这里传入了一个User对象,那么Retrofit内部是如何转换的呢?其实还是利用上面说的转换器GsonConverterFactory。

五、表单的方式传递键值对@FormUrlEncoded

Web开发中表单提交很常见,那么通过Retrofit如何实现一个表单提交的请求呢?接口层定义如下:

public interface ApiService {@POST("login")@FormUrlEncodedCall<List<User>> login(@Field("username") String username,@Field("password") String password);
}

通过@POST指明url,添加@FormUrlEncoded,然后通过@Field添加参数即可。访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);api.login("zhangsan","123456").enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {// 处理结果}@Overridepublic void onFailure(Call<User> call, Throwable t) {// 处理异常}});

六、单文件@Multipart

通过Retrofit实现单文件上传,接口层定义如下:

public interface ApiService {@Multipart@POST("register")Call<User> register(@Part MultipartBody.Part header, @Part("username") RequestBody username,@Part("password") RequestBody password);
}

这里@MultiPart的意思就是允许多个@Part了,我们这里使用了3个@Part,第一个我们准备上传个文件,使用了MultipartBody.Part类型,其余两个均为简单的键值对。访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx/").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);// 创建需要上传服务端的用户头像文件File file = new File(Environment.getExternalStorageDirectory(), "photo.png");RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);MultipartBody.Part photo = MultipartBody.Part.createFormData("photo", file.getName(), photoRequestBody);ReqeustBody usernameRequestBody = RequestBody.create(null, "zhangsan");ReqeustBody passwordRequestBody = RequestBody.create(null, "123456");api.registerUser(photo, usernameRequestBody,passwordRequestBody).enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {// 处理结果}@Overridepublic void onFailure(Call<User> call, Throwable t) {// 处理异常}});

七、多文件上传@PartMap

Retrofit实现多文件上传,接口层定义如下:

public interface ApiService {@Multipart@POST("register")Call<User> register(@PartMap Map<String, RequestBody> params, @Part("password") RequestBody password);
}

这里使用了一个新的注解@PartMap,这个注解用于标识一个Map,Map的key为String类型,代表上传的键值对的key(与服务器接受的key对应),value即为RequestBody,有点类似@Part的封装版本。访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);File file = new File(Environment.getExternalStorageDirectory(), "photo.png");RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png", file);Map<String,RequestBody> params = new HashMap<>();params.put("photo\"; filename=\"photo.png", photoRequestBody);params.put("username",  RequestBody.create(null, "zhangsan"));ReqeustBody passwordRequestBody = RequestBody.create(null, "123456");api.registerUser(params,passwordRequestBody).enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {// 处理结果}@Overridepublic void onFailure(Call<User> call, Throwable t) {// 处理异常}});

八、请求头Headers的添加

有时候,我们需要为某个请求单独添加请求头,那么如何操作呢?接口层定义如下:

  • 通过@Headers注解进行设置
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
@Headers({"Accept: application/vnd.github.v3.full+json","User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);

注意,@Headers添加的请求头不会相互覆盖,具有相同名称的所有标头将包含在请求中。

  • 使用@Header注解动态更新请求头

必须为@Header提供相应的参数,如果该值为null,则标题将被省略。否则,将对值调用toString,并使用结果

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
@GET("user")
Call<User> getUser(@HeaderMap Map<String, String> headers)

我们还可以使用OkHttp拦截器指定需要添加到每个请求的请求头

九、同步和异步请求

Call实例可以同步或者异步执行,每个Call实例只能使用一次,但是调用Call#clone()将创建一个可以使用的新实例。 在Android上,回调将在主线程上执行。在JVM上,回调将在执行HTTP请求的同一线程上发生。

十、Retrofit框架引入方式(Gradle)

implementation 'com.squareup.retrofit2:retrofit:(insert latest version)'

十一、Retrofit混淆配置

# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {@retrofit2.http.* <methods>;
}# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

十二、下载文件

Retrofit实现文件下载,接口层定义如下:

public interface ApiService {@GET("download")Call<ResponseBody> download();
}

这里直接返回类型定义为ResponseBody,然后直接拿到其byteStream(),读流即可。访问案例如下:

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://xxx").addConverterFactory(GsonConverterFactory.create()).build();ApiService api = retrofit.create(ApiService.class);api.download().enqueue(new Callback<ResponseBody>() {@Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {InputStream in = response.body().byteStream();// 进行保存文件操作 这里是主线程!!!}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {// 处理异常}});

可以看到,我们在回调onResponse中拿到了文件流,然后就可以进行写文件的操作了,但是注意这里是主线程,文件读写操作属于耗时操作,我们还得切到子线程操作,所以文件的下载操作直接使用OkHttp就行了。

进阶配置

一、配置callFactory

查看Retrofit构建过程得知,如果没有配置callFactory,那么Retrofit内部会创建默认的OkHttpClient对象作为callFactory

public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;// callFactory为空,则创建默认的OkHttpClientif (callFactory == null) {callFactory = new OkHttpClient();}// ...省略代码
}

如果需要对OkHttpClient进行详细的设置,我们需要构建OkHttpClient对象,然后通过Retrofit.Builder#callFactoy(okhttp3.Call.Factory factory)方法Retrofit.Builder#client(OkHttpClient client)或者传入。

二、配置CallAdapterFactory

默认情况下,Retrofit只能支持Call<T>类型的接口返回,如果需要和RxJava一起使用,那么需要配置RxJavaCallAdapterFactory,这样接口返回值类型就是Observable对象,即可以使用RxJava进行请求操作。

三、配置ConverterFactory

默认情况下,Retrofit只能将HTTP正文反序列化为OkHttp的ResponseBody类型,并且只能接受@Body的RequestBody类型,可以添加转换器以支持其他类型。六个成员模块采用了流行的序列化库,以方便我们使用。

Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
JAXB: com.squareup.retrofit2:converter-jaxb
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

这是一个使用GsonConverterFactory类生成GitHubService接口的实现的示例,该接口使用Gson进行反序列化。

Retrofit retrofit = new Retrofit.Builder().baseUrl("https:xxx").addConverterFactory(GsonConverterFactory.create()).build();GitHubService service = retrofit.create(GitHubService.class);

四、自定义ConverterFactory

如果需要与使用Retrofit不支持的现成格式(例如YAML,txt,自定义格式)的API进行通信,或者希望使用其他库来实现现有格式,则可以轻松创建 您自己的转换器。 创建一个扩展Converter.Factory类的类,并在构建适配器时传入实例。

Retrofit2基本使用相关推荐

  1. android端使用http2.0,android Retrofit2+okHttp3使用总结

    使用前准备 Build.gradle文件配置 dependencies配置 compile 'com.squareup.retrofit2:retrofit:2.0.0' compile 'com.s ...

  2. Retrofit2.0

    2019独角兽企业重金招聘Python工程师标准>>> Retrofit2.0设置通用header  作者 tedzyc 关注 2016.01.07 15:47* 字数 113 阅读 ...

  3. android中mvp封装,android-简单快速封装MVP+Retrofit2.0+Rxjava框架

    1.概述 对于MVP(Model View Presenter)大多数做开发的人都能说出一二,或者看到网上的对mvp的解释,对其意都有大概的了解,但让你真正写一套mvp框架,是不是发现无从下手? 曾几 ...

  4. 网络请求--Retrofit2使用方法

    Retrofit是Square开发的网络请求库, 简化了网络请求的使用, 这个库太知名了, 好处我就不多说了. 让我们看看如何使用吧? 注意: Retrofit2的beta3版本, 使用Okhttp3 ...

  5. Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP

    Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP 项目截图 这是我的目录结构 五步使用RxJava+Retrofit2+Okhttp+RxCache 第一步:导包 ...

  6. Retrofit2.0和Rxjava结合使用的简单记录

    2019独角兽企业重金招聘Python工程师标准>>> Gradle的配置(该配置是针对rxjava1.x的) compile 'com.squareup.retrofit2:con ...

  7. Retrofit2 完全解析 探索与okhttp之间的关系

    http://blog.csdn.net/lmj623565791/article/details/51304204: 本文出自:[张鸿洋的博客] 1. 概述 之前写了个okhttputils的工具类 ...

  8. Retrofit2 multpart多文件上传详解

    原文出处:http://www.chenkaihua.com/2016/04/02/retrofit2-upload-multipart-files.html Retrofit2是目前很流行的andr ...

  9. android上传头像 sockettimeoutexception,Kotlin - Retrofit2和Rxjava2封装的网络请求类(含图片上传)...

    阅读建议:本文适合熟悉Retrofit与Rxjava2的同学阅读,其中也包含一丢丢的RxLifecycle,文中不包含这两个库的使用说明.不熟悉RxJava的同学,建议去这里了解,里面包含3篇文章,均 ...

  10. android+3.0+java8_Android Retrofit2.0+RxJava3.0 基本使用

    一,ReactiveX 要学习RxJava,那么不得不提他的由来ReactiveX,ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的API.它组合了观察者模式,迭代器模式和函数 ...

最新文章

  1. 我的Android进阶之旅------解决错误: java.util.regex.PatternSyntaxException: Incorrect Unicode property...
  2. SqlServer的SSIS导入导出数据时找不到连接错误处理
  3. 小程序异常监控及错误处理
  4. php两次访问时间,php – 检查当前时间是否介于两次之间,可能会有几天的时间
  5. 《JAVA与模式》之策略模式
  6. qaxobject控制word到某一行_Word操作技巧:快速选择文本的4种技能,提高你的工作效率...
  7. 【MFC】CFrameWnd类详解
  8. 数据结构 - 链表(单向环形链表)(约瑟夫问题)
  9. 用户-第三方支付公司-银行 资金流动过程
  10. 在uipath_UiPath狂欢节Day 3——国内超级企业CFO大咖RPA案例分享!
  11. editor修改样式 vue_VUE 项目如何快速优化?
  12. 智能家居系统c语言源代码,智能家居软件设计(附源程序).doc
  13. centos 8 配置yum源并安装开发工具包
  14. 其实华为手机按下这个按钮,还能自动清理内存垃圾,真是厉害了
  15. win10系统VirtualBox虚拟机安装
  16. 将一个数组中的值按逆序重新存放。例如,原来顺序为8,6,5,4,1。要求改为1,4,5,6,8
  17. 《Python基础教程》学习笔记——异常
  18. 超简单集成华为HMS Core MLKit通用卡证识别SDK,一键实现各种卡绑定
  19. 5款类蝉妈妈抖音数据工具推荐
  20. 中国计算机学会推荐中文科技期刊目录(2019年)

热门文章

  1. Java字节码魔法数字_Java的魔法:字节码
  2. QFP、PQFP、LQFP、TQFP封装形式及PCB详解(转载)
  3. 高数 08.02 可分离变量微分方程
  4. springboot整合数据库
  5. zbox的测试例——selectAll+selectInverse
  6. Scala——函数式编程、面向对象
  7. 哪些深度相机有python接口_三种主流深度相机介绍
  8. 小柯在学JAVA之第一弹
  9. C#实现发送短信到手机
  10. Foxmail是什么邮箱?