Retrofit 基础
在 Retrofit 中使用注解的方式来区分请求类型
格式 含义 @GET 表示这是一个 GET 请求 @POST 表示这是一个 POST 请求 @PUT 表示这是一个 PUT 请求 @DELETE 表示这是一个 DELETE 请求 @HEAD 表示这是一个 HEAD 请求 @OPTIONS 表示这是一个 OPTIONS 请求 @PATCH 表示这是一个 PATCH 请求 在 Retrofit 中的参数(@Path、@Query、@QueryMap、@Body、@Field)
初始化 Retrofit
String BASE_URL = "http://102.10.10.132/api/"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .build();
GET 请求
链接 方式 http://102.10.10.132/api/News @GET(“News”)Call getItem(); /api/News/{资讯id} @GET(“News/{newsId}”)Call getItem(@Path(“newsId”) String newsId); /api/News/{资讯id}/{类型} @GET(“News/{newsId}/{type}”)Call getItem(@Path(“newsId”) String newsId, @Path(“type”) String type); /api/News?newsId={资讯id} @GET(“News”)Call getItem(@Query(“newsId”) String newsId); /api/News?newsId={资讯id}&type={类型} @GET(“News”)Call getItem(@Query(“newsId”) String newsId, @Query(“type”) String type); /api/News?newsId={资讯id}&type={类型}… @GET(“News”)Call getItem(@QueryMap Map< String,String> map); 或者 @GET(“News”)Call getItem(@Query(“newsId”) String newsId,@QueryMap Map< String,String> map); POST 请求
链接 方式 http://102.10.10.132/api/Comments/{newsId} @FormUrlEncoded@POST(“Comments/{newsId}”)CallreportComment(@Path(“newsId”) String commentId,@Field(“reason”) String reason); /api/Comments/{newsId}?access_token={access_token} @FormUrlEncoded@POST(“Comments/{newsId}”) Call reportComment(@Path(“newsId”) String commentId,@Query(“access_token”) String access_token,@Field(“reason”) String reason); /api/Comments/{newsId}?access_token={access_token} @POST(“Comments/{newsId}”)Call reportComment( @Path(“newsId”) String commentId,@Query(“access_token”) String access_token,@Body CommentBean bean); DELETE 请求
链接 方式 http://102.10.10.132/api/Comments/{newsId} @DELETE(“Comments/{commentId}”)Call deleteNewsCommentFromAccount(@Path(“commentId”) String commentId); /api/Comments/{newsId}?access_token={access_token} @DELETE(“Comments/{commentId}”)Call deleteNewsCommentFromAccount(@Path(“accountId”) String accountId,@Query(“access_token”) String access_token); PUT 请求
链接 方式 http://102.10.10.132/api/Accounts/{accountId} @PUT(“Accounts/{accountId}”)Call updateExtras(@Path(“accountId”) String accountId,@Query(“access_token”) String access_token,@Body ExtrasBean bean); 总结
- @Path:所有在网址中的参数(URL的问号前面),如:http://102.10.10.132/api/Accounts/{accountId}
- @Query:URL问号后面的参数,如:http://102.10.10.132/api/Comments?access_token={access_token}
- @QueryMap:相当于多个@Query
- @Field:用于POST请求,提交单个数据
- @Body:相当于多个@Field,以对象的形式提交
注意!!!!!!!!!
- 使用@Field时记得添加@FormUrlEncoded
若需要重新定义接口地址,可以使用@Url,将地址以参数的形式传入即可,如:
@GETCall
Retrofit 进阶
Call 引入
Retrofit 2 里引入了 call 方法。语法和 OkHttp 基本一模一样,唯一不同是这个函数知道如何做数据的反序列化。它知道如何将 HTTP 响应转换成对象。
interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors(@Path("owner") String owner,@Path("repo") String repo); } Call<List<Contributor>> call =gitHubService.repoContributors("square", "retrofit");
每个 Call 实例只能被使用一次,若想再次使用,可以通过 clone 一个之前的实例
Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); response = call.execute(); //再次使用,会报 非法异常 response = call.execute(); Call<List<Contributor>> call2 = call.clone(); // This will not throw: response = call2.execute()
Retrofit 2 支持在同一个类型中进行同步和异步请求
Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); call.enqueue(new Callback<List<Contributor>>() { @Override void onResponse(/* ... */) { // ... } @Override void onFailure(Throwable t) { // ... } });
可以随时调用 cancel 方法来取消请求
Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); call.enqueue( ); // or... call.execute(); // later... call.cancel();
参数化的 Response 对象; Response 对象增加了曾经一直被我们忽略掉的重要元数据:响应码(the reponse code),响应消息(the response message),以及读取相应头(headers)。
class Response<T> { int code(); String message(); Headers headers(); boolean isSuccess(); T body(); ResponseBody errorBody(); com.squareup.okhttp.Response raw(); }
动态 URL 参数
interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); } Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit"); Response<List<Contributor>> response = call.execute();
Retrofit 2.0 有了新的 标注:@Url ,允许你直接传入一个请求的 URL。
@GET Call<List<Contributor>> repoContributorsPaginate(@Url String url);
更多更有效的转换器(Converters)
- 每一个 converter 会被询问是否能够处理某种类型,如果可以,就会被处理,否则,询问下一个类型的 converter。如 proto convertor、JSON converter 等;注意:JSON 没有什么继承上的约束,所以我们无法通过什么确切的条件来判断一个对象是否是 JSON 对象,故 JSON 的 converters 会对任何的数据都认为是可以处理的,所以,一定要将 JSON converter 放在最后进行判断。
- Retrofit 2 已经不提供默认的 converter了。如果不显性的声明一个可用的 Converter 的话,Retrofit 是会报错的:提醒你没有可用的 Converter。因为核心代码已经不依赖序列化相关的第三方库了,我们依然提供对 Converter 的支持,不过你需要自己引入这些依赖,同时显性的声明 Retrofit 需要用的 Converter 有哪些。
更多可替换的执行机制
在此之前,Retrofit 有一个死板的 execution 流程。在 Retrofit 2 里,我们调整了整个流程,让它变得可替换(pluggable),同时允许多个。跟 converter 的工作原理很像。比如说,你有一个方法返回了一个 Call 对象,Call 是内置的 Converter 类型。比如:Retrofit 2 的执行机制:
interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> repoContributors( @Path("owner") String owner, @Path("repo") String repo); ... 现在我们可以自己定义这些了: ... @GET("/repos/{owner}/{repo}/contributors") Observable<List<Contributor>> repoContributors2( @Path("owner") String owner, @Path("repo") String repo); @GET("/repos/{owner}/{repo}/contributors") Future<List<Contributor>> repoContributors3( @Path("owner") String owner, @Path("repo") String repo); }
Retrofit 2 常见使用场景
Retrofit 2 现在依赖 OkHttp,并没有 Http Client 层的抽象。但是现在我们可以传递一个配置好的 OkHttp 实例的,如修改 OkHttp 默认的超时时长
OkHttpClient client=new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(20,TimeUnit.SECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("") .client(client) .build();
如果要添加 converter 机制,也是如添加 Client 一样的:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(ProtoConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();
如果要添加 execute 机制,即使用 RxJava 来代替 call,也是如添加 Client 一样的:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
扩展性,如 Factory 的扩展,即写属于自己的 Call Adapter Facotory
测试 Demo
ILoginService service = RetrofitInstance.getInstance().create(ILoginService.class);
Call<ResponseBody> call = service.geUserInfo("RlWW73");
/*//同步调用
Response<ResponseBody> bodyResponse = null;
try {
bodyResponse = call.execute();
String body = bodyResponse.body().string();//获取返回体的字符串
Log.e(TAG, "onClick: "+body);
} catch (IOException e) {
e.printStackTrace();
}*/
//异步调用
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
String resultBody = new String(response.body().bytes());
Log.e(TAG, "onResponse: " + resultBody);
//第一种方式:通过 Gson 解析
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(resultBody);
JsonObject object = element.getAsJsonObject();
object.get("Code").getAsInt();
Buyer buyer = new Gson().fromJson(object.get("Data"), Buyer.class);
Log.e(TAG, "onResponse: " + object.get("Code").getAsInt() + buyer.toString());
//第二种方式:通过 json 解析
JSONObject jsonObject = new JSONObject(resultBody);
int code = jsonObject.optInt("Code");
Buyer buyer1=new Gson().fromJson(object.get("Data").toString(), Buyer.class);
Log.e(TAG, "onResponse: " + jsonObject.optInt("Code")+"-->"+buyer1.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});