记录项目中的Retrofit请求参数封装


项目中联网框架使用的是Retrofit2,因为项目的接口设计了许多公共参数,需要对Retrofit网络请求参数进行进一步的封装。本文记录了参数封装的过程。

说在前面的话:由于每个公司的接口设计规则不同,这里的封装代码也会千差万别。

文章中项目的接口规则为:统一采用POST表单的方式提交到服务器,服务器返回JSON格式的数据。并且设置了公共参数,每次请求需要携带公共参数,并且添加公共的头部。

Step1

刚开始看到表单方式,觉得很激动,Retrofit2 支持 @FormUrlEncoded注解的方式来进行表单访问
所以就有了这样的Retrofit 接口设计


public interface ApiService {

    @FormUrlEncoded
    @POST("login")
    Observable> login(@Field("data") String json);
}

因为只有@Body注解的参数才能 被Converter 转换,所以这里方法的参数使用的String类型

接下来就是公共参数的设置,采用 拦截器的方式来完成

public class HttpParamInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();
        //添加公共的头部
        requestBuilder.addHeader("User-Agent", "pinxiango");
        
        String method = request.method(); 
        //接口规则规定了请求方式为 Form 表单,这里只对Post进行处理
        if ("POST".equals(method)) {  //POST 请求
            RequestBody body = request.body();

            //因为我们项目需要获取参数 进行进一步处理,需要将参数记录下来
            String data_json = ""; //传入的Json 字符串

            FormBody.Builder builder = new FormBody.Builder();

            FormBody formBody = (FormBody) body;

           int size = formBody.size();
            if (size == 0) {
                    builder.add("data", data_json);
           } else {
                //循环将传入的 表单添加到新的表单
                for (int i = 0; i < size; i++) {
                      String name = formBody.name(i);
                      String value = formBody.value(i);
                      if ("data".equals(name)) {
                            data_json = value;
                        }
                        builder.add(name, value);
                   }
              }
            } 
         

            String sign = Contacts.KEY + "-" +
                    Contacts.version + "-" +
                    Contacts.app_source + "-" +
                    data_json;
          //拼接 公共的参数
            
          
            builder.add("datetime", dateTime + "");
            builder.add("sign", sign);


            FormBody formBody = builder.build();
            //重新构建 request
            request = requestBuilder
                    .post(formBody)
                    .build();
        }

        return chain.proceed(request);
    }

}

嗯?开始愉快的使用了,用了一圈发现怎么感觉那里不对

记录项目中的Retrofit请求参数封装_第1张图片
haha
  • Retrofit 对于@FormUrlEncoded注解的Post请求不支持空参数的请求

  • 每次请求需要手动转成 Json 字符串(尤其是这一步操作,深恶痛绝)
    为了解决这个问题,对ApiService 和HttpParamInterceptor进行修改

public interface ApiService {


    @POST("login")
    Observable> login(@Body User user);

    @POST("logout")
    Observable> logout();
}

接口设计注解全部采用 @POST的形式,需要Json 数据可以直接采用@Body 的形式 ,Converter会将其转换为Json 字符串

修改后HttpParamInterceptor 代码如下

public class HttpParamInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();
        //添加公共的头部
        requestBuilder.addHeader("User-Agent", "pinxiango");


        String method = request.method();
        if ("POST".equals(method)) {  //POST 请求
            RequestBody body = request.body();

            String data_json = ""; //传入的Json 字符串

            //后台规定数据格式为 Form 表单形式
            FormBody.Builder builder = new FormBody.Builder(); 

            //由于采用的是 普通的@Post 形式
            //并且经过Converter 的转换,内容为Json字符串
            //这里直接进行读取
            Buffer buffer = new Buffer();
            body.writeTo(buffer);
            data_json = buffer.readUtf8();
            builder.add("data", data_json);

            //系统当前的时间戳
            int dateTime = (int) (new Date().getTime() / 1000);
           

            String mde_sign = Contacts.KEY + "-" +
                   data_json + "-" +
                    dateTime;
            builder.add("datetime", dateTime + "");
            builder.add("sign", mde_sign);

            //构建Form 表单
            FormBody formBody = builder.build();
            //重构请求
            request = requestBuilder
                    .post(formBody)
                    .build();
        }

        return chain.proceed(request);
    }

}

至此,参数的封装结束。可以参考以上代码 进行分页请求的分装

你可能感兴趣的:(记录项目中的Retrofit请求参数封装)