概述

Retrofit是一个OkHttp网络请求框架的封装库,Retrofit通过注解配置网络参数,可以按照我们的规则去构造实际的HTTP请求,能够灵活设置URL、头部、请求体、返回值等,是目前最优雅的一个网络框架。

添加依赖

implementation 'com.squareup.retrofit2:retrofit:2.2.0'

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'//添加对RxJava的支持
implementation 'com.squareup.retrofit2:converter-gson:2.1.0' //添加Json数据的支持 <uses-permission android:name="android.permission.INTERNET"/>//网络请求必要的权限

Retrofit基本使用三部曲

创建实例

 Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必须以 /(斜线) 结束
.build();
RetrofitService service = retrofit.create(RetrofitService.class);//创建接口的代理对象

定义接口

public interface RetrofitService {

    @GET("/pursuit/getPursuitInfo")
Call<ResponseBody> getBlog(@Query("id") int id); @GET("/pursuit/getPursuitInfo/{id}")
Call<ResponseBody> getBlog2(@Path("id") String id); }

创建 同步/异步 回调

//异步的回调
Call<ResponseBody> call = service.getBlog(123);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
Log.i("返回信息",response.body().string()+"");//打印返回信息
} catch (IOException e) {
e.printStackTrace();
} }
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();//错误信息
}
}); /*同步的回调,如果不是在一个Activity或者一个Fragment中去执行,那么也就意味着,你可以不需要开启子线程去执行网络请求。如果是在主线程,就必须开启子线程来进行同步请求
使用call.execute()同步请求,只能调用一次。如果要多次使用这个方法,需要 call.clone()重新生成新的Call实例*/ new Thread(new Runnable() {
@Override
public void run() {
try {
retrofit2.Response<ResponseBody> response = call.execute();
response.body();
} catch (IOException e) {
e.printStackTrace();
}
}
});

HTTP协议中的常用请求

GET: 请求指定的页面信息,以?分割URL和传输数据,参数之间以&相连,最多只能是1024字节,并返回实体主体,该操作用于获取信息而非修改信息

HEAD: 只请求页面的首部。

POST: POST表示可能修改变服务器上的资源的请求,.POST的安全性要比GET的安全性高

PUT: 从客户端向服务器传送的数据取代指定文档的内容。

Retrofit注解的重点详解

注解汇总

需要理解并灵活搭配使用

基本请求

Responsebody是Retrofit网络请求回来的原始数据类。get方式可以在url后面串联

@Path注解用于替换请求参数,@Query注解相当于url后面的串联,他们可以同时使用

请看下面第三种表达式:

@GET("/pursuit/getPursuitInfo?id=123")
Call<ResponseBody> getCall(); @POST("/pursuit/getPursuitInfo")
Call<ResponseBody> getBlog(@Query("id") int id); @GET("/pursuit/getPursuitInfo/{id}")
Call<ResponseBody> getBlog2(@Path("id") String id);

自定义请求

需要用到@HTTP注解

/* method:网络请求的方法,注意大小写
* path:网络请求地址路径
* hasBody:是否有请求体
* {id} 表示是一个变量*/
@HTTP(method = "GET", path = "/pursuit/getPursuitInfo/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);

请求体非Form表单

@Body是Post方式提交非Form的表单

@POST("/pursuit/getPursuitInfo")
Observable<String> getPursuitInfo(@Body User user);

请求体是Form表单

如果请求的Form表单,需要用@FormUrlEncoded标注,@Field注解用于表单字段,它和@FieldMap都需要@FormUrlEncoded配合使用

@Field和@Query都是表单字段,@FieldMap和@Query都是批量增加表单的提交域。区别如上图,一个拼接在URL上适用于get方式,一个体现在请求体上试用于post方式,区分好使用场景。

@POST("/pursuit/getPursuitInfo") 
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

设置请求头

两种请求头的,@Header用于添加不固定的请求头,作用于方法的参数。@Headers用于添加固定的请求头,作用于方法

@Headers("Authorization: authorization")
@GET("/pursuit/getPursuitInfo")
Call<ResponseBody> getUser(); @GET("/pursuit/getPursuitInfo")
Call<ResponseBody> getUser(@Header("Authorization") String authorization);

动态替换URL

用@Url替换已经设置的baseUrl

@GET
public Call<ResponseBody> profilePicture(@Url String url);

图片上传

@POST("user/updateAvatar.do")
@Multipart
Call<ResponseBody> upload(@Part("upload1\"; filename=\"image1.jpg\"") RequestBody imgs );

文件上传

发送form-encoded的数据,用于有文件上传的场景时要用 @Multipart 注解,@Part和@PartMap适用于有文件上传的情况

@POST("mobile/upload")
@Multipart
Call<ResponseBody> upload(@Part MultipartBody.Part file);

文件上传相关阅读

轻松实现多文件/图片上传/Json字符串/表单

Retrofit上传文件的参数设置

※以上就是所有参数注解的用法,需要实践灵活试用。

Retrofit与Gson

添加对gson的支持

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必须以 /(斜线) 结束
.addConverterFactory(GsonConverterFactory.create())//添加对gson的支持
.build();

建立接口,返回Bean

public interface PostRoute {
@Headers({"Content-Type: application/json","Accept: application/json"})//需要添加头
@POST("api/FlyRoute/Add")
Call<FlyRouteBean> postFlyRoute(@Body RequestBody route);//传入的参数为RequestBody
}

将Bean转换成json字符串

FlyRouteBean flyRouteBean=new FlyRouteBean();
flyRouteBean=initdata(flyRouteBean);//根据Bean类初始化一个需要提交的数据类
Gson gson=new Gson();
String route= gson.toJson(flyRouteBean);//通过Gson将Bean转化为Json字符串形式

提交json数据

RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),route); //将json转换成RequestBody请求体
Call<FlyRouteBean> call=postRoute.postFlyRoute(body);//提交

Retrifit与RxJava

引入RxJava

compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

添加对RxJava的支持

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必须以 /(斜线) 结束
.addConverterFactory(GsonConverterFactory.create())//添加对gson的支持
.client(client)//添加okhttp的支持
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加对RxJava的支持
.build();

连接超时与开启okhttp的日志打印

    private static final OkHttpClient client = new OkHttpClient.Builder().
addInterceptor(new HttpLoggingInterceptor().//开启日志信息
setLevel(HttpLoggingInterceptor.Level.BODY)).
connectTimeout(600, TimeUnit.SECONDS).//连接超时
readTimeout(600, TimeUnit.SECONDS).//读取超时
writeTimeout(600, TimeUnit.SECONDS).build();//写入超时

建立接口,返回Observable被观察者

@GET("top250")
Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);

建立观察者

Observable<String> observable =service.getTopMovie(0, 10)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable d) { } @Override
public void onNext(ResponseBody responseBody) { } @Override
public void onError(Throwable e) { } @Override
public void onComplete() { }
});

Retrofit的简单封装

retrofit工具类

public class WebManager {
private static WebManager webManager;
private RetrofitService retrofitService;
public WebManager(Context context) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(StaticConstant.HOST_PORT)//地址
.addConverterFactory(GsonConverterFactory.create())//添加gson支持
.client(client)//设置okhttp连接
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加RxJava的支持
.build();
retrofitService = retrofit.create(RetrofitService.class);
}
private static final OkHttpClient client = new OkHttpClient.Builder().
addInterceptor(new HttpLoggingInterceptor().//开启日志信息
setLevel(HttpLoggingInterceptor.Level.BODY)).
connectTimeout(600, TimeUnit.SECONDS).//连接超时
readTimeout(600, TimeUnit.SECONDS).//读取超时
writeTimeout(600, TimeUnit.SECONDS).build();//写入超时
//获取单例
public static WebManager getInstance(Context context){
if(webManager == null){
webManager = new WebManager(context);
}
return webManager;
}
//上传xx信息,使用@Field注解
public void postInfoField(Callback<ResponseBody> callback, String str){
retrofitService.getWarrant("queryApplicationForm",null,str)
.enqueue(callback);
}
//上传xx信息,使用@FieldMap注解
public void postInfoFieldMap(Callback<ResponseBody> callback, String num,String name){
Map<String, Object> map=new HashMap<>();
map.put("hotelCode",num);
map.put("hotelName",name);
retrofitService.getUnlicensedNum(map).enqueue(callback);
}
//上传xx信息,使用@Body 注解
public void postMultipartBody(Callback<ResponseBody> callback, String key,File file, String name){
MultipartBody.Builder builder= new MultipartBody.Builder().setType(MultipartBody.FORM);
if(file.exists()) {
builder.addFormDataPart("access_token", key);
builder.addFormDataPart("name", name);
builder.addFormDataPart("image", ImageUtil.imageToBase64(file.getPath()));
builder.addFormDataPart("image_type", "BASE64");
}
retrofitService.getUnlicensedCheck(builder.build()).enqueue(callback);
}
//上传xx信息,带文件,使用@Body 注解
public void postMultipartBody2(Callback<ResponseBody> callback, HotelInfo hotelInfo,String pictureCardPath,String picturePath){
Gson gson=new Gson();
String json= gson.toJson(hotelInfo);
File file = new File(pictureCardPath);
File file2 = new File(picturePath);
MultipartBody.Builder builder= new MultipartBody.Builder().setType(MultipartBody.FORM);
if(!file.exists()&&!file2.exists()) {
try {
builder.addFormDataPart("info", json);
builder.addFormDataPart("file",file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
builder.addFormDataPart("file2",file2.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file2));
retrofitService.getHotelInfoFile(builder.build()).enqueue(callback);
} catch (Exception e) {
e.printStackTrace();
Log.i("WebManager","上传异常");
}
}
} }

retrofit服务类

public interface RetrofitService {
@FormUrlEncoded
@POST("/Hotels/ExpressServlet")
Call<ResponseBody> getWarrant(@Field("type") String type, @Field("E_Code") String code,
@Field("applicationFormId") String id); @FormUrlEncoded
@POST("Hotels/NoRegisterServlet")
Call<ResponseBody> getUnlicensedNum(@FieldMap Map<String,Object> fieldMap); @POST("/rest/2.0/face/v3/person/verify")
Call<ResponseBody> getUnlicensedCheck(@Body MultipartBody builder); @Headers("Connection: close" )
@POST("/Hotels/UploadFileImgServlet")
Call<ResponseBody> getHotelInfoFile(@Body MultipartBody builder); }

RxJava相关阅读

Android异步框架 RxJava

Retrofit代码混淆配置

-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions

Android 网络框架 Retrofit2的更多相关文章

  1. Android网络框架Volley(体验篇)

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  2. Android网络框架Volley(实战篇)

      之前讲了ym—— Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看如何把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQu ...

  3. Android网络框架-Volley实践 使用Volley打造自己定义ListView

    这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影 ...

  4. Android网络框架Volley

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  5. ym—— Android网络框架Volley(终极篇)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看Android网络框架Volley(体验篇)和 ...

  6. Android网络框架之Retrofit + RxJava + OkHttp 变化的时代

    1.什么是Retrofit框架? 它是Square公司开发的现在非常流行的网络框架,所以我们在导入它的包的时候都可以看到这个公司的名字,目前的版本是2. 特点: 性能好,处理快,使用简单,Retrof ...

  7. Android网络框架源码分析一---Volley

    转载自 http://www.jianshu.com/p/9e17727f31a1?utm_campaign=maleskine&utm_content=note&utm_medium ...

  8. 【从0到1】android网络框架的选型参考

    项目会使用到 socket tcp 级的网络访问,想选取一个使用较成熟异步网络框架, 提到的网络框架: 1. volley, 2. xutils. 3. android 4. netty, 5. mi ...

  9. Android 网络框架Volley的使用

    Volley简介 在平时的开发过程中,我们的应用几乎总是在和网络打交道, 在android下的网络编程一般都是基于Http协议的 ,常见的是HttpURLConnection和HttpClient 两 ...

随机推荐

  1. [SQL]LeetCode180. 连续出现的数字 | Consecutive Numbers

    SQL架构: Create table If Not Exists Logs (Id int, Num int) Truncate table Logs insert into Logs (Id, N ...

  2. [Swift]LeetCode703. 数据流中的第K大元素 | Kth Largest Element in a Stream

    Design a class to find the kth largest element in a stream. Note that it is the kth largest element ...

  3. Python中面向对象的概念(科普)

    面向对象(OOP)基本概念 面向对象编程 —— Object Oriented Programming 简写 OOP 目标 了解 面向对象 基本概念 01. 面向对象基本概念 我们之前学习的编程方式就 ...

  4. Python档案袋(列表、元组、字典、集合 )

    列表 可以同名,有序(通过下标可找到) 取值: 1 #声明列表 2 listx=["L0","L1","L2",33,"L4&qu ...

  5. CentOS 6.5系统上安装SVN服务器

    有效地管理源代码的方式是使用工具去帮助我们管理 , SVN(Subversion)就是目前主流的源代码管理工具 , 也称为版本控制工具. 本文主要介绍CentOS6.5上安装SVN服务器,配置SVN服 ...

  6. JVM基础系列第14讲:JVM参数之GC日志配置

    说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志.而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数.今天就让 ...

  7. 死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 插入元素 插入元素,如果元素在树中存在,则替换value:如果元素不存在,则插入到对应的位置, ...

  8. EF实现批量插入

    Z.EntityFramework.BulkInsert EntityFramework 最被人诟病的地方就是它的性能,处理大量数据时的效率.此种条件下,通常会转回使用 ADO.NET 来完成任务.而 ...

  9. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  10. RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)

    在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...