Retrofit用法初识(一)
Retrofit好。
1.导入依赖包
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
2.Retrofit具体用法
(1)创建业务请求接口
public interface BookService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("name") String name, @Query("tag") String tag, @Query("start") int start, @Query("count") int count);
}
(2)创建一个Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.douban.com/v2/")
.addConverterFactory(GsonConverterFactory.create())
.build();
BookService service = retrofit.create(BookService.class);
(3)调用请求方法,得到Call实例
Call<BookSearchResponse> call = service.getSearchBooks("小王子", "", 0, 3);
(4)使用Call实例完成同异步请求
- 同步请求:
BookSearchResponse response = call.execute().body();
- 异步请求:
call.enqueue(new Callback<BookSearchResponse>() {
@Override
public void onResponse(Call<BookSearchResponse> call, Response<BookSearchResponse> response) {
asyncText.setText("异步请求结果:"
+response.body().books.get(0).altTitle);
}
@Override
public void onFailure(Call<BookSearchResponse> call, Throwable t) {
}
});
3.Retrofit其他方法
(1)Url配置
@GET("book/{id}")
Call<BookSearchResponse> getBook(@Path("id") String id);
Call<BookSearchResponse> call = service.getBook("1003078");
此时的url地址为:
https://api.douban.com/v2/book/1003078
(2)Get方法
@Query后的参数为单个,@QueryMap后的参数可以一个Map集合:
public interface BookService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options);
}
另若是Map中相同Key值,不同的value值,可以将所有的value放置在列表中,然后在同一个@Query下完成添加:
public interface BookService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("q") List<String> name);
}
最后@Query的值可以为null。
(3)Post方法
Post请求需要把请求参数放置在请求体中,而非拼接在url后面,先来看一个简单的例子:
@FormUrlEncoded
@POST("book/reviews")
Call<String> addReviews(@Field("book") String bookId,
@Field("title") String title,@Field("content") String content, @Field("rating") String rating);
- @FromURLEncoded
@FormUrlEncoded将会自动将请求参数的类型调整为application/x-www-form-urlencoded,假如content传递的参数为Good Luck,那么最后得到的请求体就是:
content=Good+Luck
@Field和@FieldMap
类似@Query与@QueryMap,
@Field注解将每一个请求参数都存放至请求体中,还可以添加encoded参数,该参数为boolean型,具体的用法为
@Field(value = "book", encoded = true) String book
encoded参数为true的话,key-value-pair将会被编码,即将中文和特殊字符进行编码转换。
而Post如果有更多的请求参数,这个时候就可以用@FieldMap:
@FormUrlEncoded
@POST("book/reviews")
Call<String> addReviews(@FieldMap Map<String, String> fields);
- @Body
如果Post请求参数有多个,那么统一封装到类中应该会更好,这样维护起来会非常方便
@FormUrlEncoded
@POST("book/reviews")
Call<String> addReviews(@Body Reviews reviews);
public class Reviews {
public String book;
public String title;
public String content;
public String rating;
}
(4)上传
- 首先还是需要新建一个interface用于定义上传方法:
public interface FileUploadService {
// 上传单个文件
@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(
@Part("description") RequestBody description,
@Part MultipartBody.Part file);
// 上传多个文件
@Multipart
@POST("upload")
Call<ResponseBody> uploadMultipleFiles(
@Part("description") RequestBody description,
@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2);
}
- 接下来我们还需要在Activity和Fragment中实现两个工具方法:
public static final String MULTIPART_FORM_DATA = "multipart/form-data";
@NonNull
private RequestBody createPartFromString(String descriptionString) {
return RequestBody.create(
MediaType.parse(MULTIPART_FORM_DATA), descriptionString);
}
@NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
File file = FileUtils.getFile(this, fileUri);
// 为file建立RequestBody实例
RequestBody requestFile =
RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);
// MultipartBody.Part借助文件名完成最终的上传
return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}
- 接下来就是最终的上传文件代码:
Uri file1Uri = ... // 从文件选择器或者摄像头中获取
Uri file2Uri = ...
// 创建上传的service实例
FileUploadService service =
ServiceGenerator.createService(FileUploadService.class);
// 创建文件的part (photo, video, ...)
MultipartBody.Part body1 = prepareFilePart("video", file1Uri);
MultipartBody.Part body2 = prepareFilePart("thumbnail", file2Uri);
// 添加其他的part
RequestBody description = createPartFromString("hello, this is description speaking");
// 最后执行异步请求操作
Call<ResponseBody> call = service.uploadMultipleFiles(description, body1, body2);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
(5)其他方法
除了Get和Post请求,Http请求还包括Put,Delete等等,用法和Post相似,所以就不再单独介绍了。
4.其他注意事项
- 添加自定义的header
我们知道http是有请求头的,有些时候我们是需要填写或者配置一下请求头的,比如说,文件上传,或者cookie保持。这里的请求头支持动态配置和静态配置。
- 静态方法
public interface BookService {
@Headers({
"Accept: application/vnd.yourapi.v1.full+json",
"User-Agent: Your-App-Name"
})
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("q") String name,
@Query("tag") String tag, @Query("start") int start,
@Query("count") int count);
}
- 动态方法
public interface BookService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(
@Header("Content-Range") String contentRange,
@Query("q") String name, @Query("tag") String tag,
@Query("start") int start, @Query("count") int count);
}
5.结尾
你做的还不够好。
咳咳,本文大面积整理(抄袭)介篇