Retrofit学习笔记
一、Retrofit简介
Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现
Retrofit执行网络请求
以一个GET请求为例,执行网路请求所需步骤:
1.创建业务请求接口
public interface BlueService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("q") 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();
BlueService service = retrofit.create(BlueService.class);
baseUrl就是网络请求URL相对固定的地址,一般包括请求协议(如Http)、域名或IP地址、端口号等,当然还会有很多其他的配置,下文会详细介绍。addConverterFactory方法表示需要用什么转换器来解析返回值,GsonConverterFactory.create()表示调用Gson库来解析json返回值
3.调用请求方法,并得到Call实例
-
同步请求
BookSearchResponse response = call.execute().body();
网络请求一定要在子线程中完成,不能直接在UI线程执行,不然会crash
-
异步请求
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) { } });
二、使用
首先需要在module的build.gradle文件中依赖相关包,配置如下
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'
引入这些包后,接下来需要对不同请求方式进行说明
Get方法
-
@Query
Get方法请求参数都会以key=value的方式拼接在url后面,Retrofit提供了两种方式设置请求参数。第一种就是像上文提到的直接在interface中添加@Query注解,还有一种方式是通过Interceptor实现,直接看如何通过Interceptor实现请求参数的添加。
public class CustomInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); HttpUrl httpUrl = request.url().newBuilder() .addQueryParameter("token", "tokenValue") .build(); request = request.newBuilder().url(httpUrl).build(); return chain.proceed(request); } }
ddQueryParameter就是添加请求参数的具体代码,这种方式比较适用于所有的请求都需要添加的参数,一般现在的网络请求都会添加token作为用户标识,那么这种方式就比较适合。
创建完成自定义的Interceptor后,还需要在Retrofit创建client处完成添加
addInterceptor(new CustomInterceptor())
-
@QueryMap
如果Query参数比较多,那么可以通过@QueryMap方式将所有的参数集成在一个Map统一传递
public interface BlueService { @GET("book/search") Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options); }
-
Query集合
假如你需要添加相同Key值,但是value却有多个的情况,一种方式是添加多个@Query参数,还有一种简便的方式是将所有的value放置在列表中,然后在同一个@Query下完成添加,实例代码如下:
public interface BlueService { @GET("book/search") Call<BookSearchResponse> getSearchBooks(@Query("q") List<String> name); }
-
@Path
如果请求的相对地址也是需要调用方传递,那么可以使用@Path注解,示例代码如下:
@GET("book/{id}") Call<BookResponse> getBook(@Path("id") String id);
Post请求
-
@field
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);
特别说明:
-
@FormUrlEncoded将会自动将请求参数的类型调整为application/x-www-form-urlencoded,假如content传递的参数为Good Luck,那么最后得到的请求体就是
FormUrlEncoded不能用于Get请求
-
@Field注解将每一个请求参数都存放至请求体中,还可以添加encoded参数,该参数为boolean型,具体的用法为
@Field(value = "book", encoded = true) String book
encoded参数为true的话,key-value-pair将会被编码,即将中文和特殊字符进行编码转换
2.@FieldMap
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; }