Retrofit是Square开发的一个Android和Java的REST客户端库。这个库非常简单并且具有很多特性,相比其他的网络库,更容易让初学者快速掌握。它可以处理GET、POST、PUT、DELETE…等请求,还可以使用picasso加载图片。
Retrofit 2.0底层依赖OkHttp实现,也就是说Retrofit本质上就是对OkHttp的更进一步封装。Retrofit和其它Http库最大区别在于通过大范围使用注解简化Http请求。
Retrofit使用注解来描述HTTP请求:
- URL参数的替换和query参数的支持
- 对象转化为请求体(如:JSON,protocol buffers等)
- 多重请求体和文件上传
Retrofit中的注解大体分为以下几类:用于标注请求方式的注解、用于标记请求头的注解、用于标记请求参数的注解。其实,任何一种Http库都提供了相关的支持,无非在retrofit中是用注解来简化。
该类型的注解用于标注不同的http请求方式,主要有以下几种:
注解 | 说明 |
---|---|
@GET | 表明这是get请求 |
@POST | 表明这是post请求 |
@PUT | 表明这是put请求 |
@DELETE | 表明这是delete请求 |
@PATCH | 表明这是一个patch请求,该请求是对put请求的补充,用于更新局部资源 |
@HEAD | 表明这是一个head请求 |
@OPTIONS | 表明这是一个option请求 |
@HTTP | 通用注解,可以替换以上所有的注解,其拥有三个属性:method,path,hasBody |
简单用例:
@GET("mobile/capture")
Call getCapture(@Query("phone") String phone);
该类型的注解用于为请求添加请求头。
注解 | 说明 |
---|---|
@Headers | 用于添加固定请求头,可以同时添加多个。通过该注解添加的请求头不会相互覆盖,而是共同存在 |
@Header | 作为方法的参数传入,用于添加不固定值的Header,该注解会更新已有的请求头 |
@Headers的示例:
//使用@Headers添加单个请求头
@Headers("Cache-Control:public,max-age=120")
@GET("mobile/active")
Call getActive(@Query("id") int activeId);
//使用@Headers添加多个请求头
@Headers({
"User-Agent:android"
"Cache-Control:public,max-age=120",
})
@GET("mobile/active")
Call getActive(@Query("id") int activeId);
@Header的示例:
@GET("mobile/active")
Call getActive(@Header("token") String token,@Query("id") int activeId);
可以看出@Header是以方法参数形势传入的
该类型的注解用于标注请求和响应的格式。
名称 | 说明 |
---|---|
@FormUrlEncoded | 表示请求发送编码表单数据,每个键值对需要使用@Field注解 |
@Multipart | 表示请求发送multipart数据,需要配合使用@Part |
@Streaming | 表示响应用字节流的形式返回.如果没使用该注解,默认会把数据全部载入到内存中.该注解在在下载大文件的特别有用 |
该类型的注解用来标注请求参数的格式,有些需要结合上面请求和响应格式的注解一起使用。
名称 | 说明 |
---|---|
@Body | 多用于post请求发送非表单数据,比如想要以post方式传递json格式数据 |
@Filed | 多用于post请求中表单字段,Filed和FieldMap需要FormUrlEncoded结合使用 |
@FiledMap | 和@Filed作用一致,用于不确定表单参数 |
@Part | 用于表单字段,Part和PartMap与Multipart注解结合使用,适合文件上传的情况 |
@PartMap | 用于表单字段,默认接受的类型是Map |
public interface PersonalProtocol {
/**
* 用户信息
* @param page
* @return
*/
@FormUrlEncoded
@POST("user/personal_list_info")
Call> getPersonalListInfo(@Field("cur_page") int page);
}
@FormUrlEncoded
注解表示from表单,另外还有@Multipart
等注解,如果接口不需要传递参数,那么@FormUrlEncoded
以及@Multipart
需要去掉
Retrofit
的使用private void requestRetrofit(){
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com/").build();
PersonalProtocol personalProtocol = retrofit.create(PersonalProtocol.class);
Call> call = personalProtocol.getPersonalListInfo(12);
call.enqueue(new Callback>() {
@Override
public void onResponse(Call> call, Response> response) {
//数据请求成功
}
@Override
public void onFailure(Call> call, Throwable t) {
//数据请求失败
}
});
}
首先将域名传入构造一个Retrofit
,然后通过retrofit
中的create
方法传入一个Java接口并得到一个PersonalProtocol
(当然PersonalProtocol
这个对象是经过处理了的,这个后面会讲到)调用getPersonalListInfo(12)
然后返回一个Call
,最后这个Call
调用了enqueue
方法去异步请求http,这就是一个基本的Retrofit
的网络请求。Retrofit2
中Call
接口的默认实现是OkHttpCall
,它默认使用OkHttp3
作为底层http
请求client
。
其实Retrofit还有很多方法,我们现在选两个一起来看看:
OkHttpClient okHttpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(buildGson()))
.build();
addConverterFactory
方法中使用了gson
去解析json
此外,我们再来看看RxJava的使用:
OkHttpClient okHttpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder().baseUrl("www.xxxx.com")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(buildGson()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
addCallAdapterFactory
方法中使用了RxJavaCallAdapterFactory
,网络请求也需要修改:
PersonalProtocol personalProtocol = retrofit.create(PersonalProtocol.class);
rx.Observable observable = personalProtocol.getPersonalListInfo(12);
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())//最后在主线程中执行
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
//请求失败
}
@Override
public void onNext(PersonalInfo personalInfo) {
//请求成功
}
});
同时PersonalProtocol
接口也需要改变:
public interface PersonalProtocol {
/**
* 用户信息
* @param page
* @return
*/
@FormUrlEncoded
@POST("user/personal_list_info")
Observable getPersonalListInfo(@Field("cur_page") int page);
// Call> getPersonalListInfo(@Field("cur_page") int page);
}