Android | Retrofit简单封装及注解的使用

此篇文章主要记录下自己使用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,贴个图,大概格式就是这样


image.png

封装好后该如何使用?

简单粗暴上代码

 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来匹配

目前在项目中常用的一些注解和封装方法就酱紫啦,写的比较基础,也没有实在性的技术语言去讲解,但把如何使用的例子都贴的很清楚,我觉得有些东西能说出来并不一定会用,但是当你会用了就一定能说,不应该把对技术的学习停留在理论上 -.而且对于菜鸟的我来说,在网上查到的一些结束贴,大部分都是文字说明文字说明文字说明....看的到最后头大了都不知道该怎么去用,把怎么用讲清楚最实在。
还有很多注解没有写到,等以后用了再继续补充~~
希望在技术的路上越走越好~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容