Retrofit2是利用接口、方法和注解参数来声明定义请求的。
默认采用OkHttp(retrofit1.x中用的是Square包下的,retrofit2.0用的是okHttp3,两者api有较大不同)做请求代理,序列化没有默认需要自己定义。
可以同步发送请求,也可以异步发送请求 异步时候需要定义回调,同步时候需要处理异常。
缓存采用OkHttp自带缓存进行处理。
dependencies {
compile 'com.google.code.gson:gson:2.3'
compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.squareup.okhttp:okhttp:2.4.0'
}
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
从retrofit2.0开始,在Retrofit包中将不包含Converter,所以需要手动的插入一个转换器在Retrofit中,否则只能接受String结果,所以Retrofit2.0不再依赖Gson。
public class ArticlesModel {
.....
}
/**
* 爱卡汽车app首页请求接口
* http://a.xcar.com.cn/interface/6.0/newsList.php/*type=1&provinceId=xxx&cityId=xxx&offset=xxx&limit=xx*x&ver=xxx
*/
interface MainHttpServer{
//设置头信息 保存缓存
@Headers("Cache-Control: public, max-age=604800 ,max-stale=2419200")
// maxAge max-stale感觉两个类类似 都是设置最大失效时间,失效则不使用 需要服务器配合
//get请求
@GET("newsList.php")
Call requestArticles(
@Query("type") String type,
@Query("provinceId") String provinceId,
@Query("cityId") String cityId,
@Query("offset") String offset,
@Query("limit") String limit,
@Query("ver") String ver
);
}
//初始化Retrofit .baseUrl必须得有
Retrofit.Builder build = new Retrofit.Builder()
.baseUrl("http://a.xcar.com.cn/interface/6.0/")
.addConverterFactory(GsonConverterFactory.create());
//通过.build创建Retrofit
Retrofit retrofit = build.build();
//通过retrofit.create() 动态代理拿到接口
MainHttpServer service = retrofit.create(MainHttpServer.class);
//调用接口的方法 其实内部进行了url拼接 准备请求等操作 因为service实际是一个动态代理类
Call call = service.requestArticles("1","","",String.valueOf(mOffset),String.valueOf(mOffset+LIMIT),"6.0");
//创建请求回调
Callback mainCallBack = new ArticlesCallBack(loadType);
//异步执行请求 如需同步 调用execute()方法
call.enqueue(mainCallBack);
private class ArticlesCallBack implements Callback {
@Override
public void onResponse(Call call, Response response) {
//请求成功
..............
}
@Override
public void onFailure(Call call, Throwable t) {
//请求失败
.............
}
}
//初始化OkHttp所用的缓存 以及OKhttp请求
File cacheFile = new File(mContext.getCacheDir(), "xcar-cache");
Cache cache = new Cache(cacheFile,10 * 1024 * 1024);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
//在初始化Retrofit的时候 将OkHttpClient设置进去
Retrofit.Builder build = new Retrofit.Builder().client(client);
//使用缓存需要在接口方法里面声明(见接口定义)
//@Headers("Cache-Control: public, max-age=604800 ,max-stale=2419200")
Retrofit.Builder build = new Retrofit.Builder()
.baseUrl("http://a.xcar.com.cn/interface/6.0/")
.addConverterFactory(GsonConverterFactory.create());
上边的baseUrl为http://a.xcar.com.cn/interface/6.0/
1.@GET("newsList.php")
Call requestArticles(
@Query("type") String type,
@Query("provinceId") String provinceId,
@Query("cityId") String cityId,
@Query("offset") String offset,
@Query("limit") String limit,
@Query("ver") String ver
);
这种形式的请求组成的url为:
http://a.xcar.com.cn/interface/6.0/newsList.php/type=1&provinceId=xxx&cityId=xxx&offset=xxx&limit=xxx&ver=xxx
2.@GET("/newsList.php")
Call requestArticles();
这种形式的请求组成的url为:
http://a.xcar.com.cn/newsList.php
3.@GET("newsList.php/{id}/user")
Call requestArticles(@path("id") int id);
假设传入的id为111,最后生成的地址为:
http://a.xcar.com.cn/interface/6.0/newsList.php/111/user
Retrofit的使用就是以下几步:
Retrofit2中可以使用的Converter有以下几种
Simple XML com.squareup.retrofit2converter-simplexml:2.0.0-beta3
//添加一个GSON的转换器
Retrofit.Builder build = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create());
Converter可以添加一个也可以添加多个如下所示,额外添加一个Proto的Converter,一个错误的例子如下
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ProtoConverterFactory.create())
.build();
!!注意上述写法是错误的!!
添加 converter 的顺序很重要 GSON必须放在最后,下面是正确的
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(ProtoConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
public interface MyApiEndpointInterface {
// Request method and URL specified in the annotation
// Callback for the parsed response is the last parameter
@Headers("Cache-Control: public, max-age=604800 ,max-stale=2419200")
@GET("/users/{username}")
Call getUser(@Path("username") String username);
@GET("/group/{id}/users")
Call> groupList(@Path("id") int groupId, @Query("sort") String sort);
@POST("/users/new")
Call createUser(@Body User user);
}
上面的例子中可以看到:
表单提交多参数的数据 @Multipart + @Part
@Multipart
@POST("/some/endpoint")
Call someEndpoint(@Part("name1") String name1, @Part("name2") String name2)
表单提交多参数数据 @FormUrlEncoded + @Field
@FormUrlEncoded
@POST("/user/edit")
User updateUser(@Field("first_name") String first, @Field("last_name") String last);
表单提交一个Map的键值对 @FormUrlEncoded + @FieldMap
@FormUrlEncoded
@POST("/some/endpoint")
Call someEndpoint(@FieldMap Map names);
Header注解 @Headers
静态注解
对个header
interface FixedHeader{
@Headers({ //静态Header
“Accept: application/vnd.github.v3.full+json”,
“User-Agent: Retrofit-Sample-App”
})
@GET(“/”)
Response getResponse();
}
动态注解
单一header
interface DynamicHeader{
@Headers(“Cache-Control: max-age=640000”) //静态Header
@GET(“/”)
Response getResponse(@Header(“header1”)String header1,@Header(“header2”)String header2); //动态Header,其value值可以在调用这个方法时动态传入.
}
一般地,base URL是在实例化 Retrofit instance 的时候定义的。Retrofit 2 允许你在注解里面重写base URL 。
@POST("https://api.github.com/api/v3")
call.execute()同步方法只能执行一次。第二次会出异常 想要再用 .clone()
Call> call =
gitHubService.repoContributors("square", "retrofit");
response = call.execute();
// This will throw IllegalStateException:
response = call.execute();
Call> call2 = call.clone();
// This will not throw:
response = call2.execute();
可以调用cancel()来立刻取消请求
Call> call =
gitHubService.repoContributors("square", "retrofit");
call.enqueue( );
// or...
call.execute();
// later...
call.cancel();
在CallBack回调里面有Response类,在该类中可以得到响应码,响应信息,响应头(code message handers)
注意:如果返回码是200 但是最终返回false的情况 实际是无法判断返回到底是什么 自己处理budy即可
注意必须声明Converters,现在没有默认的Converter
经过测试: baseUrl必须设置,如果 声明接口时@GET使用了完整的url路径,那么baseUrl就会被忽略,否则就是拼接url
Retrofit使用了三行代码就完成了创建链接+请求
// 创建一个GitHub接口的请求
XcarInter xcar = retrofit.create(XcarInter.class);
//创建Call的实例 准备请求
Call call = xcar.requestData("xxx", "xxx");
//执行请求
call.enqueue(new MyCallBack(){
@Override
public void onResponse(Call call, Response response) {
...
}
@Override
public void onFailure(Call call, Throwable t) {
...
}
});
在retrofit.create()的时候,create()方法内部执行动态代理得到接口对象,这时候xcar这个接口对象并不是implements对象,当xcar调用了接口对应的方法后执行的其实是动态代理的方法,看上去调用接口方法,实际Retrofit将Xcar接口翻译成为一个HTTP请求,也就是源码中的MethodHalder对象。实际是MethodHalder对象来处理后续的请求操作。