[]Retrofit
Retrofit是一个HTTP网络请求框架的封装。Retrofit 2.0内置OkHttp,Retrofit用于接口的封装,OkHttp用于执行网络请求操作,
Retrofit请求网络,使用 Retrofit 接口层封装请求参数,Header,Url 等信息。然后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用户的需求对结果进行解析的过程。
先看一下官方案例
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
[]Url 配置
Retrofit支持的协议有GET,POST,PUT,DELETE,HEAD,PATCH。还可以直接用HTTP来自定义请求。这些协议均以注解的形式进行配置。
请求的完整Url是通过baseUrl()的baseUrl参数和注解的value参数组合起来的。
具体的规则如下:
value是绝对路径的形式:
value = “/apath”,baseUrl = “http://host:port/a/b”
Url = “http://host:port/apath”
value是相对路径,baseUrl 是目录形式:
value = “apath”,baseUrl = “http://host:port/a/b/”
Url = “http://host:port/a/b/apath”
value是相对路径,baseUrl 是文件形式:
value = “apath”,baseUrl = “http://host:port/a/b”
Url = “http://host:port/a/apath”
value是完整的 Url:
value = “http://host:port/aa/apath“,baseUrl = “http://host:port/a/b”
Url = “http://host:port/aa/apath”
建议采用第二种方式来配置,并尽量使用同一种路径形式。
[]参数类型
()Path(用于URL替换)
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
()Query & QueryMap(用于GET请求)
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
如果有多个Query时,采用QueryMap 。
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
()Body Body配置的对象(User)会转化为json,服务器获取参数时需要注意
@POST("users/new")
Call<User> createUser(@Body User user);
()Field & FieldMap(用于POST请求)
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
同样FieldMap用于有多个Field 。
()Part & PartMap(用于上传文件)
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
如果上传多个文件采用PartMap
()设置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);
[]动态配置
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
[]通过拦截器(Interceptor)设置Header
OkHttpClient client = new OkHttpClient.Builder()
//错误是否重连
.retryOnConnectionFailure(false)
//设置超时,默认是10s
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("Content-Type", "")
.addHeader("Accept", "")
.addHeader("Cookie", "you cookie")
.build();
return chain.proceed(request);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.client(client)
.build();
GitHubService service = retrofit.create(GitHubService.class);
[]Converter (必须要指定,不然请求不成功。可以指定多个)
()返回的结果为json,设置能自动解析成对象。
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
//防止你需要调整json里面的一些格式,比如DateFormat。
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
GitHubService service = retrofit.create(GitHubService.class);
Square提供的官方Converter modules列表
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
()自定义Converter
1.自定义请求Converter(RequestBodyConverter)
假如上传图片时参数是File对象而不是RequestBody对象。
@Multipart
@PUT("user/photo")
Call<User> uploadImg(@Part("photo") File file);
public class UploadImgConverterFactory extends Converter.Factory {
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return new UploadImgRequestBodyConverter();
}
static class UploadImgRequestBodyConverter implements Converter<File, RequestBody> {
@Override
public RequestBody convert(File value) throws IOException {
/**
*上传文件
*/
//RequestBody.create(MediaType.parse("application/otcet-stream"), value);
/**
*上传图片
*/
return RequestBody.create(MediaType.parse("image/jpeg"), value);
}
}
}
2.自定义响应Converter(ResponseBodyConverter)
假如服务器返回的是字符串。
public class StringConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new StringResponseConverter();
}
static class StringResponseConverter implements Converter<ResponseBody, String> {
@Override
public String convert(ResponseBody value) throws IOException {
return value.toString();
}
}
}
构造Retrofit时需要添加自定义Converter。
[]与RxJava配合使用
compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
//与RxJava配合
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
MyService service = retrofit.create(MyService.class);
[]OKHttp其他设置
()离线缓存策略
File directory = new File(this.getExternalCacheDir(), "");
Cache cache = new Cache(directory, 1024 * 1024 * 50);
OkHttpClient client = new OkHttpClient.Builder()
//开启缓存
.cache(cache)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (没有网络) {
request.newBuilder()
//FORCE_NETWORK 只走网络
//FORCE_CACHE 只走缓存
//无网络时只从缓存中读取
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (有网络) {
//设置缓存超时时间1个小时
int maxAge = 60 * 60;
response.newBuilder()
//清除头信息,因为服务器如果不支持,
//会返回一些干扰信息,不清除下面无法生效
.removeHeader("Pragma")
//设置缓存超时时间
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
//设置超时为4周
int maxStale = 60 * 60 * 24 * 28;
response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "ppublic, only-if-cached, max-stale=" + maxStale)
.build();
}
return response;
}
}).build();
()公共参数
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
HttpUrl modifiedUrl =originalRequest.url()
.newBuilder()
.addQueryParameter("platform", "adnroid")
.addQueryParameter("version", "1.2.0")
.build();
Request request =originalRequest.newBuilder()
.url(modifiedUrl)
.build();
......
return chain.proceed(request);
}
[]Mock Server
相关文章
Retrofit官网
http://square.github.io/retrofit/
Retrofit GitHub项目
https://github.com/square/retrofit
RxJava 与 Retrofit 结合的最佳实践
http://gank.io/post/56e80c2c677659311bed9841