Retrofit
来源:互联网 发布:怎么修改淘宝密码 编辑:程序博客网 时间:2024/06/02 01:06
Retrofit 是Square公司推出的简化HTTP请求的第三方库, 是对其公司另一网络请求库OkHttp的封装
实现了对响应数据解析的封装, 可以不需要自己去解析网络请求回来的数据. 使用方法采用注解的形式.
想要了解Retrofit的使用, 需要先了解Okhttp的用法. 因为Retrofit是基于Okhttp的封装. 同样也可以用Okhttp的方法.
参考文档:
官方
- GitHub
- 使用指南
- 开发文档
博客
- 深入浅出Retrofit
- 你真的会用Retrofit2吗?
演示
这里我以获取网站内容为例子
完整接口链接
http://liangjingkanji.coding.me/2017/03/03/TabLayout/
添加依赖
建议以官方GitHub最新版为准
compile 'com.squareup.retrofit2:retrofit:2.2.0'
创建实例
通过Retrofit的构造器创建实例对象
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://liangjingkanji.coding.me/") .build();
- baseUrl 一般存放的是服务器的域名, 记住必须以”/”结尾, 否则报异常
注意: 在Retrofit2版本以前baseUrl通过加不加”/”来判断@Path是绝对路径还是相对路径. 但是在2.0强制要求必须以”/”结尾.
创建接口
在Retrofit中每个接口都对应一个网络请求, 该接口是用于设置请求的参数或者路径以及响应体类型
public interface BlogService { @GET("2017/03/03/{index}") Call<ResponseBody> getBlog(@Path("index") String index); }
- @GET(“2017/03/03/{index}”) 表示以GET方式请求链接. 后面的字符串是拼接地址. “{}”大括号内部是占位符的含义. 最终会用getBlog里面的参数替代.
- @Path(“index”) 表示其修饰的参数String index 将会替代之前提到的占位符”{index}”
创建服务
通过接口的字节码创建服务
BlogService service = retrofit.create(BlogService.class);
执行回调
通过接口的方法得到回调
Call<ResponseBody> call = service.getBlog(2); // 得到回调call.enqueue(new Callback<ResponseBody>() { // 执行回调 // 成功回调 @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { System.out.println(response.body().string()); // 打印响应体 } catch (IOException e) { e.printStackTrace(); // 读取响应体失败 } } // 失败回调 @Override public void onFailure(Call<ResponseBody> call, Throwable t) { t.printStackTrace(); // 打印请求错误异常信息 }});
全部请求方法
retrofit支持六种请求方式, 通过注解的方式使用. 上面的示例我们就使用了@GET 注解
- GET
- POST
- PUT
- DELETE
- HEAD
- OPTIONS
- HTTP
其中HTTP是以通过值来决定请求方式的注解
public interface BlogService { /** * method 表示请求的方法,区分大小写 * path表示路径 * hasBody表示是否有请求体 */ @HTTP(method = "GET", path = "blog/{id}", hasBody = false) Call<ResponseBody> getBlog(@Path("id") int id);}
这里我只讲解常用的GET和POST请求方式
GET请求
关键注解: @GET
可选参数: String path 表示一个绝对或者相对/完整的URL路径
这里请求方式注解的参数虽然说都是可选参数, 但是如果你完全不写还是会报错的. 除非你在服务接口的方法参数里面加个@URL 注解指定了路径.
如果你想直接用baseUrl的路径可以使用@GET("/")
或者@GET(".")
代表使用baseUrl作为完整路径. POST请求方式同样处理.
URL拼接
GET请求本身就是拼接URL. 所以你可以在路径里面直接写请求参数.
@GET("users/list?sort=desc")
如果在想传入值的情况下可以使用以下注解
关键注解 @Query 用于修饰方法参数
必须参数: String value 参数名
可选参数: boole encoded 是否对参数进行URLEncode编码
这里我没有把接口的路径写到@GET注解里面. 这种写法和之前示例里面的一样.
public interface GitHubService { @GET Call<String> request(@Query("key") String value @URL String path);}
如果是参数名相同值不同的多个参数可以用可变参数写. 这算是数组类型参数.
后面这种可变参数的写法我不会再提.
@GET Call<ResponseBody> list(@Query("category") String... categories, @URL String path);
结果
路径/list?category=bar&category=baz.
如果GET是多个参数一个个写是很麻烦的. 所以需要使用到Map集合
关键注解: @QueryMap 修饰Map集合
可选参数: boolean encoded 是否对参数进行URLEncode编码
@GET("/search") Call<ResponseBody> list(@QueryMap Map<String, String> filters);
结果
路径 /search?foo=bar&kit=kat.
**注:**URLEncode编码是对URL地址中的特殊字符进行编码. 防止被服务器错误识别. 例如”&”默认为参数拼接的含义. 如果请求参数中包含这个特殊字符怎么办? URLEcode就会将其换成其他字符. 详情可以Google.
POST请求
关键注解: @POST
可选参数: String path 绝对或者相对/完整的URL路径
下面我会介绍Post请求的几种请求方式. 可以归纳为:
- 表单
- 字符串
- 流
FormUrl提交
即最常见的表单提交. 用于提交键值对的基本类型的参数. 注意不能上传文件. 也就是说@Field只能修饰基本数据类型.
关键注解: @FormUrlEncoded
@POST("/form")@FormUrlEncodedCall<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
单参数
POST请求肯定是要带有参数的. POST参数注解和GET参数注解类似
关键注解: @Field
必须参数: String value 表单参数的名字
可选参数: boolean encoded 是否对参数进行URLEncode编码
@FormUrlEncoded @POST("/") Call<ResponseBody> example( @Field("name") String name, @Field("occupation") String occupation);
多参数
使用Map集合参数提交
关键注解: @FieldMap
可选参数: boolean encoded 是否对参数进行URLEncode编码
@FormUrlEncoded @POST("/things") Call<ResponseBody> things(@FieldMap Map<String, String> fields);
Multipart提交
多类型提交一般用于文件. 也可以作为表单提交键值对
关键注解: @Multipart
@POST("/form")@MultipartCall<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
单参数
关键注解: @Part
可选参数:
- String value 参数名
- String encoding
@POST("/form")@MultipartCall<ResponseBody> testFileUpload2(@Part MultipartBody.Part file);
多参数
关键注解: @PartMap
可选参数: String encoding
@Multipart @POST("/upload") Call<ResponseBody> upload( @Part("file") RequestBody file, @PartMap Map<String, RequestBody> params);
关键注解: @Multipart
流类型提交
关键注解: @Streaming
请求参数
除了上面所提到的提交参数意外还有
路径拼接
GET注解后面一般不是都会有个相对路径的字符串嘛. 这个字符串里面可以通过写{}
包裹任意内容. 被包裹的都是占位符. 最终会被Path注解修饰的参数替代. 最开始的示例就是用了这个注解.
关键注解: @Path
interface GitHubService { @GET("/repos/{owner}/{repo}/contributors")List<Contributor> repoContributors( @Path("owner") String owner, @Path("repo") String repo);}
请求体
使用一个对象作为请求体提交, 例如使用Json进行参数的提交. 该请求体同样可以作为@GET请求的参数提交.
关键注解: @Body
@POST("users/new")Call<User> createUser(@Body User user);
这个Body修饰的参数要求必须是Retrofit指定的响应体转换类型. 也就是说要求请求体和响应体都要求同样. 否则只能用Response作为请求体.
请求头
单请求头
关键注解: @Header
必须参数: String value 请求头参数
@GET("/") Call<ResponseBody> foo(@Header("Accept-Language") String lang);
多请求头
使用String[] 作为请求头. 注意只有@Headers可以单独使用. 其他的请求头注解都只能修饰方法参数
关键注解: @Headers
必须参数: String[] value 请求头参数
单请求头
@Headers("Cache-Control: max-age=640000") @GET("/")
多请求头
@Headers({ "X-Foo: Bar", "X-Ping: Pong" }) @GET("/")
还可以使用Map集合作为请求头参数
关键注解: @HeaderMap
@GET("/search") void list(@HeaderMap Map<String, String> headers);
Response 响应参数
关键类: Response
public static <T> Response<T> success(T body)public static <T> Response<T> success(T body, okhttp3.Headers headers)public static <T> Response<T> success(T body, okhttp3.Response rawResponse)public static <T> Response<T> error(int code, okhttp3.ResponseBody body)public static <T> Response<T> error(okhttp3.ResponseBody body, okhttp3.Response rawResponse)public okhttp3.Response raw()// 状态码public int code()// 响应消息, 如果未知返回nullpublic String message()public okhttp3.Headers headers()// 是否成功, 状态码在200~300之间([200..300))public boolean isSuccessful()// 得到响应体, 该响应体属于泛型, 详情介绍看Retrofit转换器public T body()// 访问失败返回的响应体, 即状态码不在200~300之间public okhttp3.ResponseBody errorBody()
转换器
前面提过Retrofit支持直接返回你想要的类型对象. 例如返回的Json数据直接返回JsonBean对象. 而不是Response对象. 同样你想直接返回String类型也行.
除了添加Retrofit依赖外, 还需要添加转换响应体的依赖包. 官方提供六种常用转换库
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
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
这里我使用了Gson转换器进行讲解
关键类
Gson
添加Gson转换器的依赖, 这里的依赖包版本号跟随Retrofit即可
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
创建接口. “.”的路径表示使用baseUrl作为完整路径. 这里的TimeBean是我创建的一般的JsonBean类
public interface InterfaceService { @GET(".") Call<TimeBean> getServerTime();}
创建实例的时候增加一个方法addConverterFactory
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://mob.mgtvshop.com/interface/get_time/") .addConverterFactory(GsonConverterFactory.create()) // 添加转换器 .build();InterfaceService service = retrofit.create(InterfaceService.class);Call<TimeBean> serverTime = service.getServerTime();serverTime.enqueue(new Callback<TimeBean>() { @Override public void onResponse(Call<TimeBean> call, Response<TimeBean> response) { // response的body()将直接返回Jsonbean类 System.out.println(response.body().getMsg()); } @Override public void onFailure(Call<TimeBean> call, Throwable t) { }});
注:如果返回的Json不能被解析. 则返回null. 报空指针异常. 建议进行异常捕捉.
Retrofit
Build
public Retrofit.Builder baseUrl(okhttp3.HttpUrl baseUrl)// 字符串链接必须以 "/"结尾, 一般为域名public Retrofit.Builder baseUrl(String baseUrl)// 设置一个Okhttp客户端public Retrofit.Builder client(okhttp3.OkHttpClient client)// 设置回调实例public Retrofit.Builder callFactory(okhttp3.Call.Factory factory)// 添加序列化或反序列化转换器public Retrofit.Builder addConverterFactory(Converter.Factory factory)public Retrofit.Builder addCallAdapterFactory(CallAdapter.Factory factory)public Retrofit.Builder callbackExecutor(Executor executor)public Retrofit.Builder validateEagerly(boolean validateEagerly)public Retrofit build()
Retrofit
public <T> T create(Class<T> service)
请求网络
和Okhttp不同的是Retrofit的回调方法都已在主线程内. 可以直接更新UI.
Call
该方法和okHttp的Call类没什么区别.
同步执行
注意, Android不支持同步网络请求. 如果要使用需要处理 NetworkOnMainThreadException 异常
Response<T> execute() throws IOException
示例:
try { Response<ResponseBody> bodyResponse = call.execute(); String body = bodyResponse.body().string();//获取返回体的字符串 Log.i("wxl", "body=" + body); } catch (IOException e) { e.printStackTrace(); }
异步执行
void enqueue(Callback<T> callback)
示例:
call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Response<ResponseBody> response) { try { Log.i("wxl", "response=" + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Throwable t) { Log.i("wxl", "onFailure=" + t.getMessage()); } });
更多方法
// 是否执行了网络请求boolean isExecuted()// 取消网络请求void cancel()// 是否执行了取消网络请求boolean isCanceled()// 创建新的网络请求Call<T> clone()// 得到请求对象okhttp3.Request request()
网络请求的回调
Interface Callback<T>
实现接口需要重写两个方法:
成功:
void onResponse(Call<T> call, Response<T> response) // 成功时返回的响应体
失败:
该失败指的是服务器错误或者因为异常请求的原因. 例如Json解析错误也会回调该方法
void onFailure(Call<T> call, Throwable t) // 失败时抛出的异常
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- Retrofit
- retrofit
- Retrofit
- retrofit
- 直接拿来用!十大Material Design开源项目
- [LintCode]373.奇偶分割数组
- 安卓开发之EventBus的使用分享以及例子源码
- 点击流日志分析项目实战开发流程
- MINI PCI-E 引脚定义
- Retrofit
- Erasure Coding
- Git tag 给当前分支打标签
- Supervisord远程命令执行漏洞分析(CVE-2017-11610)
- 多边形寻路算法简单介绍
- GridLayout
- 2017秋招-技术岗-腾讯-CDG-提前批(2轮技术电面+1轮HR电面)
- VC显示jpg图像
- git 如何获取指定 tag 代码