android retrofit 2.0公共参数,详解Retrofit2.0 公共参数(固定参数)

本文主要介绍了Retrofit2.0 公共参数(固定参数),分享给大家,具体如下:

在实际项目中,对于有需要统一进行公共参数添加的网络请求,可以使用下面的代码来实现:

RestAdapter restAdapter = new RestAdapter.Builder()

.setEndpoint(ctx).setRequestInterceptor(new RequestInterceptor() {

@Override

public void intercept(RequestFacade request) {

request.addQueryParam("publicParams", "1");

}

}).setConverter(new BaseConverter())

.build();

在RestAdapter的实例化对象的时候,为其指定一个RequestInterceptor接口的实现类即可,在该类中,可以对请求体的相关参数进行设置,如addHeader、addQueryParam等。

不过遗憾的是Retrofit2.0已经没有了该类,该怎么做呢?通过Interceptor实现。

Interceptor是拦截器, 在发送之前, 添加一些参数, 或者获取一些信息。

/**

* 封装公共参数(Key和密码)

*

*/

public class CommonInterceptor implements Interceptor {

private final String mApiKey;

private final String mApiSecret;

public CommonInterceptor(String apiKey, String apiSecret) {

mApiKey = apiKey;

mApiSecret = apiSecret;

}

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

String marvelHash = ApiUtils.generateMarvelHash(mApiKey, mApiSecret);

Request oldRequest = chain.request();

// 添加新的参数

HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()

.newBuilder()

.scheme(oldRequest.url().scheme())

.host(oldRequest.url().host())

.addQueryParameter(MarvelService.PARAM_API_KEY, mApiKey)

.addQueryParameter(MarvelService.PARAM_TIMESTAMP, ApiUtils.getUnixTimeStamp())

.addQueryParameter(MarvelService.PARAM_HASH, marvelHash);

// 新的请求

Request newRequest = oldRequest.newBuilder()

.method(oldRequest.method(), oldRequest.body())

.url(authorizedUrlBuilder.build())

.build();

return chain.proceed(newRequest);

}

}

Okhttp3使用了装饰者模式, 使用Builder添加Interceptor。

CommonInterceptor commonInterceptor = new CommonInterceptor(

"key", "Secret");

OkHttpClient client = new OkHttpClient.Builder()

.addInterceptor(commonInterceptor)

.build();

// 适配器

Retrofit retrofit = new Retrofit.Builder()

.baseUrl("url")

.addConverterFactory(GsonConverterFactory.create()

.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

.client(client)

.build();

有时候你找到了一条线,就能顺着线找到更多。

背景

在 Android Http API 请求开发中经常遇到这样的需求:每一次请求带上一个或者多个固定不变的参数,例如:

设备唯一标识:device_id = 7a4391e28f309c21

业务唯一标识:uid = 2231001

平台类型:platform = android

客户端版本号:version_code = 6

这些参数是每一次发生请求都需要的,我们姑且称他们为公共参数(或者基础参数)。公共参数一般以 header line、url query 或者 post body(较少) 这些形式插入请求。

实现

如果使用 OkHttp 作为 http request client, 这件事情就变得简单多了。OkHttp 提供了强大的拦截器组件 (Interceptor):

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

也就是说,OkHttp 的拦截器功能之一就是对将要发出的请求进行拦截、改造然后再发出。这正是我们想要的。BasicParamsInterceptor 实现了 okhttp3.Interceptor 接口。

实现 public Response intercept(Chain chain) throws IOException 方法。使用 Builder 模式,暴露以下接口:

addParam(String key, String value)

post 请求,且 body type 为 x-www-form-urlencoded 时,键值对公共参数插入到 body 参数中,其他情况插入到 url query 参数中。

addParamsMap(Map paramsMap)

同上,不过这里用键值对 Map 作为参数批量插入。

addHeaderParam(String key, String value)

在 header 中插入键值对参数。

addHeaderParamsMap(Map headerParamsMap)

在 header 中插入键值对 Map 集合,批量插入。

addHeaderLine(String headerLine)

在 header 中插入 headerLine 字符串,字符串需要符合 -1 != headerLine.indexOf(“:”) 的规则,即可以解析成键值对。

addHeaderLinesList(List headerLinesList)

同上,headerLineList: List 为参数,批量插入 headerLine。

addQueryParam(String key, String value)

插入键值对参数到 url query 中。

addQueryParamsMap(Map queryParamsMap)

插入键值对参数 map 到 url query 中,批量插入。

示例

使用 Buider 模式创建 Interceptor 对象,然后调用 OkHttp 的 addInterceptor(Interceptor i) 方法将 interceptor 对象添加至 client 中:

BasicParamsInterceptor basicParamsInterceptor =

new OkPublicParamsInterceptor.Builder()

.addHeaderParam("device_id", DeviceUtils.getDeviceId())

.addParam("uid", UserModel.getInstance().getUid())

.addQueryParam("api_version", "1.1")

.build();

OkHttpClient client = new OkHttpClient.Builder()

.addInterceptor(basicParamsInterceptor)

.build();

TODO

自动时间戳公共参数的支持

动态参数的支持(例如登录后插入服务器返回的 uid)

源码

basicparamsinterceptor应用

配置基本提交参数

我们可以建一个拦截器,这里我举例加些简单的系统参数,如下:

class HttpBaseParamsLoggingInterceptor implements Interceptor{

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

Request.Builder requestBuilder = request.newBuilder();

RequestBody formBody = new FormBody.Builder()

.add("userId", "10000")

.add("sessionToken", "E34343RDFDRGRT43RFERGFRE")

.add("q_version", "1.1")

.add("device_id", "android-344365")

.add("device_os", "android")

.add("device_osversion","6.0")

.add("req_timestamp", System.currentTimeMillis() + "")

.add("app_name","forums")

.add("sign", "md5")

.build();

String postBodyString = Utils.bodyToString(request.body());

postBodyString += ((postBodyString.length() > 0) ? "&" : "") + Utils.bodyToString(formBody);

request = requestBuilder

.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"),

postBodyString))

.build();

return chain.proceed(request);

}

}

上面Utils类是使用的okio.Buffer里面的工具类。通过RequestBody构建要上传的一些基本公共的参数,然后通过”&”符号在http 的body里面其他要提交参数拼接。然后再通过requestBuilder重新创建request对象,然后再通过chain.proceed(request)返回Response 。

接下来在创建OkHttpClient对象的时候修改为如下代码:

mOkHttpClient = new OkHttpClient.Builder()

.addInterceptor(interceptor)

.addInterceptor(new HttpBaseParamsLoggingInterceptor())

.build();

这样就添加好了一些基本的公共参数。

下面我们借助BasicParamsInterceptor实现,代码如下:

public class BasicParamsInterceptor implements Interceptor {

Map queryParamsMap = new HashMap<>();

Map paramsMap = new HashMap<>();

Map headerParamsMap = new HashMap<>();

List headerLinesList = new ArrayList<>();

private BasicParamsInterceptor() {

}

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

Request.Builder requestBuilder = request.newBuilder();

// process header params inject

Headers.Builder headerBuilder = request.headers().newBuilder();

if (headerParamsMap.size() > 0) {

Iterator iterator = headerParamsMap.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry entry = (Map.Entry) iterator.next();

headerBuilder.add((String) entry.getKey(), (String) entry.getValue());

}

}

if (headerLinesList.size() > 0) {

for (String line: headerLinesList) {

headerBuilder.add(line);

}

}

requestBuilder.headers(headerBuilder.build());

// process header params end

// process queryParams inject whatever it's GET or POST

if (queryParamsMap.size() > 0) {

injectParamsIntoUrl(request, requestBuilder, queryParamsMap);

}

// process header params end

// process post body inject

if (request.method().equals("POST") && request.body().contentType().subtype().equals("x-www-form-urlencoded")) {

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

if (paramsMap.size() > 0) {

Iterator iterator = paramsMap.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry entry = (Map.Entry) iterator.next();

formBodyBuilder.add((String) entry.getKey(), (String) entry.getValue());

}

}

RequestBody formBody = formBodyBuilder.build();

String postBodyString = bodyToString(request.body());

postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);

requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString));

} else { // can't inject into body, then inject into url

injectParamsIntoUrl(request, requestBuilder, paramsMap);

}

request = requestBuilder.build();

return chain.proceed(request);

}

// func to inject params into url

private void injectParamsIntoUrl(Request request, Request.Builder requestBuilder, Map paramsMap) {

HttpUrl.Builder httpUrlBuilder = request.url().newBuilder();

if (paramsMap.size() > 0) {

Iterator iterator = paramsMap.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry entry = (Map.Entry) iterator.next();

httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());

}

}

requestBuilder.url(httpUrlBuilder.build());

}

private static String bodyToString(final RequestBody request){

try {

final RequestBody copy = request;

final Buffer buffer = new Buffer();

if(copy != null)

copy.writeTo(buffer);

else

return "";

return buffer.readUtf8();

}

catch (final IOException e) {

return "did not work";

}

}

public static class Builder {

BasicParamsInterceptor interceptor;

public Builder() {

interceptor = new BasicParamsInterceptor();

}

public Builder addParam(String key, String value) {

interceptor.paramsMap.put(key, value);

return this;

}

public Builder addParamsMap(Map paramsMap) {

interceptor.paramsMap.putAll(paramsMap);

return this;

}

public Builder addHeaderParam(String key, String value) {

interceptor.headerParamsMap.put(key, value);

return this;

}

public Builder addHeaderParamsMap(Map headerParamsMap) {

interceptor.headerParamsMap.putAll(headerParamsMap);

return this;

}

public Builder addHeaderLine(String headerLine) {

int index = headerLine.indexOf(":");

if (index == -1) {

throw new IllegalArgumentException("Unexpected header: " + headerLine);

}

interceptor.headerLinesList.add(headerLine);

return this;

}

public Builder addHeaderLinesList(List headerLinesList) {

for (String headerLine: headerLinesList) {

int index = headerLine.indexOf(":");

if (index == -1) {

throw new IllegalArgumentException("Unexpected header: " + headerLine);

}

interceptor.headerLinesList.add(headerLine);

}

return this;

}

public Builder addQueryParam(String key, String value) {

interceptor.queryParamsMap.put(key, value);

return this;

}

public Builder addQueryParamsMap(Map queryParamsMap) {

interceptor.queryParamsMap.putAll(queryParamsMap);

return this;

}

public BasicParamsInterceptor build() {

return interceptor;

}

}

}

只要像上面一样配置就行了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中使用 Retrofit 上传图片可以通过 `@Multipart` 和 `@Part` 注解实现。以下是 Retrofit 2.0 实现图文上传的方法总结: 1. 添加依赖库 在项目的 `build.gradle` 文件中添加以下依赖库: ```groovy implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' ``` 2. 创建 Retrofit 实例 ```java Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); ``` 3. 创建 API 接口 ```java public interface ApiService { @Multipart @POST("upload") Call<ResponseBody> upload( @Part("description") RequestBody description, @Part MultipartBody.Part file); } ``` 其中,`@Multipart` 注解表示这是一个包含文本和文件的表单;`@POST("upload")` 表示上传的 URL 地址;`@Part("description") RequestBody description` 表示上传的文本参数,`description` 是参数名,可以自己定义;`@Part MultipartBody.Part file` 表示上传的文件参数。 4. 创建请求参数 ```java File file = new File(filePath); RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file); MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile); RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), "description"); ``` 5. 发送网络请求 ```java ApiService apiService = retrofit.create(ApiService.class); Call<ResponseBody> call = apiService.upload(description, body); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { // 成功上传后的处理 } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 上传失败后的处理 } }); ``` 以上就是 Retrofit 2.0 实现图文上传的方法总结。注意,在 `AndroidManifest.xml` 文件中需要添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值