转自:http://www.jianshu.com/p/308f3c54abdd
Retrofit是Square出品的Android Http请求框架,是基于Okhttp的(Okhttp也是该机构搞的)。Retrofit经历了从1.x版本到2.x版本,是构造REST风格的HTTP客户端的利器。
1.优势
首先,Retrofit相对与以前的HTTP请求方式,如HttpURLConnection和OkHttpClient有很大优势。首先对于url构造和请求实体构造等过程,
HttpURLConnection或OkHttpClient还需要手动拼接url,还需要手动对上传或返回的数据流进行操作。如果想进行解析,还需要自己再去手动引入一些解析框架如Gson等。
此外,还需要用异步控制的方案或者框架如AyncTask/handler/Rxjava等,手动再与网络请求进行耦合。如果设计不当,会导致这几个框架之间耦合较大,
导致如果有一天想替换掉某一部分(比如想用Rxjava替换Call或Gson替换Jackson)会很困难。
Retrofit在这几个方面都比较有优势:首先在构造HTTP请求时,我们只需要去构造接口的方法,框架会帮我们去实现这些方法。
按规则去构造url,指定请求参数。可以直接用解析框架生成请求实体或解析结果。得到想要的异步请求的对象(Call/RxJava/RxJava2/guava/CompletableFuture)。
请求构造更方便,同时与解析框架和异步请求框架解耦(通过Retrofit.addxxxFactory指定用不同的框架),可以更便捷的替换不同的解析框架或者异步框架。
此外,性能上,由于Retrofit是基于OkHttp的,所以其继承了OkHttp的优秀性能.
HttpURLConnection或OkHttpClient还需要手动拼接url,还需要手动对上传或返回的数据流进行操作。如果想进行解析,还需要自己再去手动引入一些解析框架如Gson等。
此外,还需要用异步控制的方案或者框架如AyncTask/handler/Rxjava等,手动再与网络请求进行耦合。如果设计不当,会导致这几个框架之间耦合较大,
导致如果有一天想替换掉某一部分(比如想用Rxjava替换Call或Gson替换Jackson)会很困难。
Retrofit在这几个方面都比较有优势:首先在构造HTTP请求时,我们只需要去构造接口的方法,框架会帮我们去实现这些方法。
按规则去构造url,指定请求参数。可以直接用解析框架生成请求实体或解析结果。得到想要的异步请求的对象(Call/RxJava/RxJava2/guava/CompletableFuture)。
请求构造更方便,同时与解析框架和异步请求框架解耦(通过Retrofit.addxxxFactory指定用不同的框架),可以更便捷的替换不同的解析框架或者异步框架。
此外,性能上,由于Retrofit是基于OkHttp的,所以其继承了OkHttp的优秀性能.
2. retrofit的使用
(1)定义接口
public interface BlogService {
@GET("blog/{id}")
Call<ResponseBody> getBlog(@Path("id") int id);
}
(2)获取代理实例
BlogService service = retrofit.create(BlogService.class);
(3)接口调用
Call<ResponseBody> call = service.getBlog(2);
// 用法和OkHttp的call如出一辙,
// 不同的是如果是Android系统回调方法执行在主线程
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();
}
});
(4)结果输出
{"code":200,"msg":"OK","data":{"id":2,"date":"2016-04-15 03:17:50","author":"怪盗kidou","title":"Retrofit2 测试2","content":
"这里是 Retrofit2 Demo 测试服务器2"},"count":0,"page":0}
3.注解功能
包含GET. POST. PUT. DELETE.PATCH.HEAD.OPTIONS.HTTP等4.表单请求, 文件上传
/**
* Map的key作为表单的键
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
5.不同的参数类型
作用于方法的heads
作用于形参的Header, Body, Field, FieldMap,Part,PartMap, Path, Query, QueryMap, Url
例如:
public interface BlogService {
@GET("blog/{id}") //这里的{id} 表示是一个变量
Call<ResponseBody> getBlog(/** 这里的id表示的是上面的{id} */@Path("id") int id);
}
public interface BlogService {
@GET("/headers?showAll=true")
@Headers({"CustomHeader1: customHeaderValue1", "CustomHeader2: customHeaderValue2"})
Call<ResponseBody> testHeader(@Header("CustomHeader3") String customHeaderValue3);
}
6.自定义Gson返回值解析
返回后按这个时间格式进行解析
Gson gson = new GsonBuilder()
//配置你的Gson
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
//可以接收自定义的Gson,当然也可以不传
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
7.bean的传输
public interface BlogService {
@POST("blog")
Call<Result<Blog>> createBlog(@Body Blog blog);
}
Gson gson = new GsonBuilder()
//配置你的Gson
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:4567/")
//可以接收自定义的Gson,当然也可以不传
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
BlogService service = retrofit.create(BlogService.class);
Blog blog = new Blog();
blog.content = "新建的Blog";
blog.title = "测试";
blog.author = "怪盗kidou";
Call<Result<Blog>> call = service.createBlog(blog);
call.enqueue(new Callback<Result<Blog>>() {
@Override
public void onResponse(Call<Result<Blog>> call, Response<Result<Blog>> response) {
// 已经转换为想要的类型了
Result<Blog> result = response.body();
System.out.println(result);
}
@Override
public void onFailure(Call<Result<Blog>> call, Throwable t) {
t.printStackTrace();
}
});
8.同步和异步请求
异步
call.enqueue(new Callback<InfoBean>(){});
同步
call.execute
9. 可使用Rxjava的CallAdapter, Observable代替Call<T>
public interface BlogService {
@POST("/blog")
Observable<Result<List<Blog>>> getBlogs();
}
BlogService service = retrofit.create(BlogService.class);
service.getBlogs(1)
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<Result<List<Blog>>>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.err.println("onError");
}
@Override
public void onNext(Result<List<Blog>> blogsResult) {
System.out.println(blogsResult);
}
});
10. 可自定义的CallAdapter和Converter
public interface BlogService {
@POST("/blog")
Observable<Result<List<Blog>>> getBlogs();
}
BlogService service = retrofit.create(BlogService.class);
service.getBlogs(1)
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<Result<List<Blog>>>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.err.println("onError");
}
@Override
public void onNext(Result<List<Blog>> blogsResult) {
System.out.println(blogsResult);
}
});
略