Retrofit与okhttp都是Square公司出品,retrofit就是在okhttp的基础上做了一层封装。网络请求相关操作交给Okhttp处理,我们只需要通过简单的配置就能使用retrofit来进行网络请求了。
Retrofit使用入门
首先创建一个接口:
public interface UserService {
@GET("users/{user}/lessons")
Call<List<Lesson>> listLessons(@Path("user") String user);
}
这个接口是为了通过一个url获取用户课程列表的接口,当然看着这个url地址好像也不是一个完整的能够使用的url地址,确实是这样的,Retrofit请求的地址是由两部分组成的,一部分是后面要介绍的Retrofit对象中的baseUrl和类似上面接口中的path地址共同构成的。
接下来我们是不是要定义一个实现该接口的类呢 ? 当然不是的啦。我们接下来要做的是只需构造一个Retrofit对象即可,至于原理,后面会说到。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.test.com/")
.build();
UserService service = retrofit.create(UserService.class);
Call<List<Lesson>> lessonCall = service.listLessons("test");
Response<List<Lesson>> result = null;
//同步调用
result = lessonCall.execute();
//异步调用
lessonCall.enqueue(new Callback<List<Lesson>>() {
@Override
public void onResponse(Call<List<Lesson>> call, Response<List<Lesson>> response) {
result = response.body();
}
@Override
public void onFailure(Call<List<Lesson>> call, Throwable t) {
t.printStackTrace();
}
});
这样就能轻易的调用http请求了,当然了,这只是一个小小的简单的demo,Retrofit的功能不止这些。
Retrofit使用更上一层楼
前面我们弄了一个很基本的一个例子,下面我们将更进一步使用Retrofit更多的功能。
请求类型: 我们都知道http的请求类型有GET
,POST
,DELETE
,PUT
,HEAD
,PATCH
这些类型,而与之相对应的,Retrofit也包含了相对应的注解给予支持,@GET
,@POST
,@DELETE
,@PUT
,@HEAD
,@PATCH
使用对应的注解即可。
请求参数:
-
@Query && @QueryMap
:@Query
用于http请求的单个query参数传递;@QueryMap
用于多个参数传递,键值对。 -
@Field && @FieldMap
:@Field
用于post请求的单个参数传递;@FieldMap
用于post请求多个参数传递。 -
@Header && @HeaderMap
:@Header
用于单个请求头参数;@HeaderMap
用于多个请求头参数传递。 -
@Part && @PartMap
:@Part
用于单个文件的上传;@PartMap
用于多个文件上传。 -
@Path
:用于path路径变量的传递接收。
上述示例代码:
@GET("users/{user}/lessons")
Call<List<Lesson>> listLessons(@Path("user") String user);
@GET("users/getuser")
Call<User> getUser(@Query("userId")String userId);
@GET("users/getUserByCondition")
Call<List<User>> getUserByCondition(@QueryMap Map<String,String> conditionMap);
@POST("users/authorization")
Call<User> authorization(@HeaderMap Map headerMap);
@Multipart//当有文件需要上传时加入
@POST("users/add")
Call<User> addUser(@FieldMap Map userInfo, @Part("photo")MultipartBody.Part file);
上面这些示例都是可以直接返回对应的结果类型,但如果我们想做一个通用的Retrofit封装的http请求工具类,那就只好返回最原始的string类型,毕竟不同请求返回结果类型不同,像这样:
public interface CommonHttpService{
@GET
Call<String> getHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap);
@FormUrlEncoded
@POST
Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @FieldMap Map<String,String> formMap);
@POST
Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @Body String body);
}
你会发现与前面的有些许不同,首先呢,@POST
或@GET
后面没有跟上一部分path路径了,而是改由参数中的@Url String url
在调用方法时传入,增加了灵活性。
Converter
如果仅仅是这样是返回不了对应的结果类型的,需要用到converter,converter的作用就是将RequestBody或ResponseBody转换为我们需要的类型,例如前面的我们想要使请求返回String类型还需要加上依赖:
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-scalars</artifactId>
<version>LATEST</version>
</dependency>
然后在构造Retrofit对象时,加上ScalarsConverterFactory
的配置:
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
ScalarsConverterFactory
里面包含了对ResponseBody进行String,原始数据类型及其包装类的转换。
目前,Retrofit已经有了几个官方的converter:
//uses Gson for serialization to and from JSON
Gson: com.squareup.retrofit2:converter-gson
//uses Jackson for serialization to and from JSON
Jackson: com.squareup.retrofit2:converter-jackson
//uses Moshi for serialization to and from JSON
Moshi: com.squareup.retrofit2:converter-moshi
//A Converter which uses Protocol Buffer binary serialization
Protobuf: com.squareup.retrofit2:converter-protobuf
//A Converter which uses Wire for protocol buffer-compatible serialization.
Wire: com.squareup.retrofit2:converter-wire
//A Converter which uses Simple for XML serialization.
Simple XML: com.squareup.retrofit2:converter-simplexml
//A Converter which supports converting strings and both primitives and their boxed types to text/plain bodies.
Scalars : com.squareup.retrofit2:converter-scalars
这些converter已经能基本满足我们日常的需要了,但凡事有例外,比如我们要加密解密,要改写结果等,所以这时候就需要我们自己来写converter.我们以自定义一个 String Converter作为一个例子:
-
自定义converter:
先定义一个converter factory:
public class CustomStringConverterFactory extends Converter.Factory {
public static CustomStringConverterFactory create() {
return new CustomStringConverterFactory();
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
if (type == String.class) {
return new CustomStringConverter();
}
return null;
}
}
这里我们只是将ResponseBody进行转换,如果你同时要将RequestBody进行转换,那就同时要覆写public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit)
方法.
定义Converter,转换的逻辑在这里面进行:
public class CustomStringConverter implements Converter<ResponseBody, String> {
@Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
}
最后一步就是将converterfactory加入到Retrofit对象构造中使用:
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com") .addConverterFactory(CustomStringConverterFactory.create())
.build();
好了,这样就能愉快的使用你自己定义的converter了,这里需要注意的是你如果添加的converter有多个的话小心顺序。