此篇文章主要记录下自己使用Retrofit后简易的封装,和相对全面的请求类型的注解使用方法,也是对知识点的一个总结和复习。
Retrofit是什么?
简单来说Retrofit是一个网络请求框架,基于OkHttp做了进一步封装,更好的适用于RESTful URL格式风格,通过注解配置参数,可以灵活的设置URL、请求头、请求体等。
优点
- 超级解耦
- 处理速度快
- 使用灵活方便
- 可以使用注解控制请求的参数
封装
public class RetrofitManager {
private static RetrofitManager mRetrofitManager;
private Retrofit mRetrofit;
private static Context mContext;
public RetrofitManager(Context context) {
this.mContext = context;
initRetrofit();
}
public static synchronized RetrofitManager getInstance(){
if (mRetrofitManager == null){ mRetrofitManager = new RetrofitManager(mContext);}
return mRetrofitManager;
}
private void initRetrofit(){
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//添加拦截器
builder.addInterceptor(new ResponseInterceptor ());
builder.addInterceptor(new RequestInterceptor ());
OkHttpClient client = builder
//设置请求超时时间
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
mRetrofit = new Retrofit.Builder()
.baseUrl(AlderApiService.BASE_URL)
// addConverterFactory 对服务器数据进行解析
.addConverterFactory(GsonConverterFactory.create())//利用Gson解析返回的json
.addConverterFactory(ScalarsConverterFactory.create())
.client(client)
.build();
}
public <T> T createReq(Class<T> reqServer){
return mRetrofit.create(reqServer);
}
}
一般使用时只用调用这个类就行了,这里主要添加了请求的拦截器、设置请求的超时时间、对添加请求的base url、添加对服务器返回数据的解析。
拦截器
public class ResponseInterceptor implements Interceptor {
private final String TAG = "ResponseInterceptor ";
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
if(response!= null){
if ( response.header("token") != null ){
//获取请求头中的token 并保存在sp中
final String token = response.header("token");
SharedPreferencesUtils.getInstance().putString(SharedPreferencesUtils.TOKEN,token);
Log.e(TAG,"保存在本地的token为:"+token);
}
}
return response;
}
}
获取Response的请求头内容,项目里只用到了token,所以这里只获取了token进行保存。
public class RequestInterceptor implements Interceptor {
}
} private final String TAG = "RequestInterceptor ";
@Override
public Response intercept(Chain chain) throws IOException {
final Request.Builder builder = chain.request().newBuilder();
String token = SharedPreferencesUtils.getInstance().getString(SharedPreferencesUtils.TOKEN,"");
if (!token.isEmpty()&& null!=token&& !"".equals(token)){
//添加请求头,携带token
builder.addHeader("token",token);
Log.i(TAG,"携带的本地token为:"+token);
}
return chain.proceed(builder.build());
给Request请求头中添加token。
Retrofit Service
我是主要在这里管理各个请求和base url,贴个图,大概格式就是这样
封装好后该如何使用?
简单粗暴上代码
public void registerSubmit(String name,String pwd,String email){
mIRegisterView.showSubmitWaitDialog();
RetrofitManager retrofitManager = new RetrofitManager(mContext);
AlderApiService.RegisterService registerService = retrofitManager.createReq(AlderApiService.RegisterService.class);
Call<Result> requestBodyCall = registerService.register(name,pwd,email);
requestBodyCall.enqueue(new Callback<Result>() {
@Override
public void onResponse(Call<Result> call, Response<Result> response) {
mIRegisterView.dismissSubmitWaitDialog();
Result result = response.body();
Log.i(TAG,"result : "+result.toString());
if(response.body() != null){
if (result.isResult()){
//success
}else {
//fail
}
}else {
mIRegisterView.OnRegisterFailed(ErrorCode.REQUEST_BODY_ERROR);
}
}
@Override
public void onFailure(Call<Result> call, Throwable t) {
mIRegisterView.dismissSubmitWaitDialog();
mIRegisterView.OnRegisterFailed(ErrorCode.NETWORK_ERROR);
}
});
}
注解的使用
下面列举的不是全部的注解,只是列举了在不同请求中遇到过使用过的注解。
POST请求
1. 普通的表单格式提交
@FormUrlEncoded 表单格式
@POST post请求方式
@Field 表单提交参数
一般这三个注解会一起使用,例如:
@FormUrlEncoded
@POST("v1/user/login")
Call<Result> login(@Field("userName") String userName);
这里@Field 中的userName是接口中定义的参数名,后面的userName是本地调用时传的参数
2. 提交json格式
@Headers 添加请求头
@Body 请求携带的参数(对象类型)
这里添加请求头和我们前面在拦截器中添加都可以,因为这个请求方式是极少数,所以只是在这里单独添加,内容类型为json
@Headers({"Content-Type:application/json","Accept: application/json"})
@POST("v1/user/remove")
Call<Result> deleteUser(@Body RequestBody requestBody);
@Body 就是传入的参数为RequestBody类型
这个方法调用时传入的参数为这样
RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),json.toString());
一般这种提交是用在批量删除的时候,将id集合以json的形式提交。
3. 路径中携带参数
@Path 将参数放在路径中
@FormUrlEncoded
@POST("v1/panel/{imei}")
Call<Result<Integer>> armControl(@Path("imei") String imei,@Field("armingLevel") int armingLeve);
@Path 有一些提交的参数是明文提交,也就是直接在url路径中显示的,这时用到的注解就是TA
GET请求
1. 普通get
@GET get请求方式
@GET("v1/user/info")
Call<Result<AccountInformation>> getAccount();
@GET 这个注解就不用做过多解释了,和post为两种请求方式
2. 带参get请求①
@GET("v1/camera/{deviceID}")
Call<GetCamera> getCameraInfo(@Path("deviceID") Integer deviceID);
这里有用到@Path,用法其实是一样的,在url中携带参数。
3. 带参get请求②
@Query 请求携带参数
@QueryMap 请求携带参数集合
@GET("v1/notification")
Call<Result<Map<String,List<Notification>>>> getNotification(@Query("cameraId") String cameraId);
@Query 在一定意义上和@Path是差不多的,最终的参数都是在请求的url中,@Query 是不需要我们自己在url中写参数的key,url最终的效果是v1/notification?cameraId=xxx,用上面的栗子来看的话 @Path url最终的效果是v1/camera/xx
DELETE请求
@DELETE 删除
@DELETE("rest/{deviceID}")
Call<String> deleteCamera(@Path("deviceID") String deviceID);
一般这样的操作,在后台提供的接口时也需要使用RESTful风格中的@DELETE来匹配
目前在项目中常用的一些注解和封装方法就酱紫啦,写的比较基础,也没有实在性的技术语言去讲解,但把如何使用的例子都贴的很清楚,我觉得有些东西能说出来并不一定会用,但是当你会用了就一定能说,不应该把对技术的学习停留在理论上 -.而且对于菜鸟的我来说,在网上查到的一些结束贴,大部分都是文字说明文字说明文字说明....看的到最后头大了都不知道该怎么去用,把怎么用讲清楚最实在。
还有很多注解没有写到,等以后用了再继续补充~~
希望在技术的路上越走越好~~