Android网络请求使用Retrofit+OkHttp,如何获取请求参数 ?

木木

 Retrofit是一个非常优秀的网络库,默认支持OkHttp,Retrofit与OkHttp共同出自于Square公司,Retrofit其实就是对OkHttp做了一层封装。把网络请求都交给给了OkHttp,我们只需要通过简单的配置就能使用Retrofit来进行网络请求了。
 Retrofit现在最新版本是2.1,OkHttp最新版本是3.4.1,两者相比前一代版本都有较大的改动,由于本文重点是描述如何在网络请求中获取参数,如需了解更多请关注RetrofitOkHttp官网。下文分别以Retrofit1.x+OKHttp2.x和Retrofit2.x+OKHttp3.x进行讲解。
 1、Retrofit1.x+OKHttp2.x
 点我达项目由于上线已经一年多,使用的版本比较低,Retrofit版本为1.9,OKHttp版本为2.5。如需获取请求参数,为了统一处理第一想法就是通过拦截器实现,Retrofit及OkHttp都支持拦截器,但是Retrofit拦截器却没有提供获取请求参数内容的方法。所以如果要在Retrofit层做处理,可以采取另外一方式。Retrofit支持自定义client,我们可以继承OkClient,获取到参数进行相关的处理。相关代码如下:

public class MyClient extends OkClient {  
    public MyClient(OkHttpClient client) {  
        super(client);  
    }  
    @Override  
    public Response execute(Request request) throws IOException {  
        //在这里获取到request后就可以做任何事情了  
        return super.execute(request);  
    }  
}  

RestAdapter.Builder builder = new RestAdapter.Builder();  
builder.setClient(new MyClient(new OkHttpClient()));  
RestAdapter adapter = builder.build();  

那么在OkHttp层怎么做呢?使用拦截器,代码如下:

okHttpClient.networkInterceptors().add(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException{ 
       Request request = chain.request();
       //在这里获取到request后就可以做任何事情了
       return null;
    }
});

2、Retrofit2.x+OKHttp3.x
 如果在项目中希望使用响应式编程,那么Retrofit就需要更新至2.x版本,同时需要更新OkHttp至3.x版本。 Retrofit2.x有个比较大的变化点就是不再支持自定义网络client必须使用OKHttp3.x, 网络相关全部交给OKHttp,很多处理方式需要做出改动,比如只能使用OKHttp提供的拦截器。此时如需获取参数,只能在OKHttp上做文章,比如重写OKHttp或者使用拦截器。这里只介绍拦截器的方式,具体代码如下:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
Interceptor myInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                //在这里获取到request后就可以做任何事情了  
                Response response = chain.proceed(request);
                return response;
            }
        };


 Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiService.HOST)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

 通过以上方式获取参数之后,就可以对参数进行统一处理了,比如加密或者增加请求头等。 另外Retroift和OKHttp的request也不一样,get方式都一样,post请求的时候获取参数的区别比较大,这里分别给出两者post请求获取参数的相关代码。
 OKHttp3.x获取post请求参数body的方式:

RequestBody requestBody= request.body();
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = Charset.forName("UTF-8");
MediaType contentType = requestBody.contentType();
if (contentType != null) {
   charset = contentType.charset(UTF8);
}
String paramsStr = buffer.readString(charset);

 Retrofit1.x获取post请求参数body的方式:

String bodyParams = "";
TypedOutput body = request.getBody();
if (body != null) {
  try {
      if (!(body instanceof TypedByteArray)) {
         String bodyMime = body.mimeType();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         body.writeTo(baos);
         body = new TypedByteArray(bodyMime, baos.toByteArray());
       }
       bodyParams = new String(((TypedByteArray) body).getBytes(),MimeUtil.parseCharset(body.mimeType()));
   } catch (Exception e) {
        e.printStackTrace();
   }
}

 对参数进行处理之后需要构建新的request,OKHttp3.x构建新的request:

Request.Builder requestBuilder = request.newBuilder();
if(request.body() instanceof FormBody){
   FormBody.Builder newFormBody = new FormBody.Builder();
   FormBody oldFormBody = (FormBody) request.body();
   for(int i = 0;i<oldFormBody.size();i++){
      newFormBody.addEncoded(oldFormBody.encodedName(i),oldFormBody.encodedValue(i));
   }
   newFormBody.add("sign","******");
   requestBuilder.method(request.method(), newFormBody.build());
}
Request newRequest = requestBuilder.build();

Retrofit1.x构建新的Request:

TypedOutput body = new TypedByteArray(requestType, params.getBytes());
Request newRequest = new Request(request.getMethod(), url,request.getHeaders(), body);

 好了,Android网络请求使用Retrofit+OkHttp,获取参数以及对参数修改之后重新构建request的方法和关键代码就介绍到这里。