android retrofit添加编码,Android中用Retrofit+Rxjava搭建网络请求

d03c2c4d2c79

image.png

前言

最近,有不少小伙伴都在问Retrofit怎么用,近期笔者的几个项目上都用到了这个框架,所以,为了防止宇宙被破坏,为了维护世界的和平(认真脸)!我决定,还是写一篇关于Retrofit的使用说明吧。

准备工作

工欲善其事必先利其器,要想使用Retrofit,当然首先你得在你的项目里面添加相关的依赖,下面是笔者项目里添加的依赖:

dependencies{

compile'com.android.support:appcompat-v7:23.4.0' // V7包支持

compile'com.squareup.retrofit2:retrofit:2.0.2' // 这个是Retrofit的依赖

compile'com.squareup.retrofit2:converter-gson:2.0.2' // 如果要是用Gson转换的话,需要添加这个依赖

compile'com.squareup.retrofit2:adapter-rxjava:2.0.2' // 用于Retrofit支持RxJava

compile'io.reactivex:rxjava:1.1.0' // RxJava

compile'io.reactivex:rxandroid:1.1.0' // RxAndroid

}

请求封装

一个网络框架接入后,当然不能直接就这么用了,一点简单的封装是必要的。首先,当然是单例模式,然后就是相关的属性设置,不多说,上代码:

RXClientGenerator.java

public class RXClientGenerator {

private static volatile RXApi rxApi;

private static Retrofit retrofit;

private String getBaseUrl() {

return "http://www.weather.com.cn/"; // 服务器地址,笔者写例子用的是一个天气的接口

}

private RXClientGenerator() {

// Retrofit是对OkHttp的封装,所以,在初始化之前,要首先初始化OkHttp

OkHttpClient client = new OkHttpClient.Builder()

.addInterceptor(new NetInterceptor()) // 这行代码添加了一个拦截器,我们后面说

.build();

// 好了,这里开始初始化Retrofit

retrofit = new Retrofit.Builder()

.baseUrl(getBaseUrl()) // 这里设置了服务器的地址,可以解释为所有网络请求地址前面的公共部分

.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 你要使用RxJava吗?加上这个吧

.addConverterFactory(GsonConverterFactory.create()) // 如果你的项目中返回的数据是json格式,那么可以添加这行代码,在获取服务器返回数据的时候直接转换成相关的Bean对象

.client(client) // 把之前初始化好的OkHttp对象添加进去

.build();

}

private static class Helper {

static final RXClientGenerator INSTANCE = new RXClientGenerator();

}

public static RXClientGenerator getInstance() {

return Helper.INSTANCE;

}

public synchronized RXApi createClient() {

if (null == rxApi)

return rxApi = retrofit.create(RXApi.class);

else

return rxApi;

}

}

接下来就是网络请求接口的定义,直接上代码

RXApi.java

public interface RXApi {

/**

* 获取天气数据

*/

@GET("data/sk/101010100.html") // 这里是接口的地址,会直接拼接到之前的baseUrl后面

Observable getWeather(); // 尖括号中的泛型是返回数据的类型

/**

* 获取天气数据

*/

@GET("data/sk/101010100.html")

Observable getWeather2(@Query("uid") String uid, // 参数是基本类型时,使用@Query注解,括号中是参数名

@Body WeatherBean body // 参数是对象时,使用@Body注解

);

}

数据Bean

WeatherBean.java

public class WeatherBean {

private WeatherinfoBean weatherinfo;

public WeatherinfoBean getWeatherinfo() {

return weatherinfo;

}

public void setWeatherinfo(WeatherinfoBean weatherinfo) {

this.weatherinfo = weatherinfo;

}

public static class WeatherinfoBean {

private String city;

private String temp1;

private String temp2;

private String weather;

public String getCity() {

return city;

}

public String getTemp1() {

return temp1;

}

public String getTemp2() {

return temp2;

}

public String getWeather() {

return weather;

}

}

}

就这样,对于Retrofit的简单封装就完成了

Retrofit的使用

对Retrofit的简单封装后,就可以在你的项目中使用它进行网络请求了。

RXClientGenerator.getInstance().createClient() // 单例模式获取请求对象

.getWeather() // 定义在RXApi中的接口方法

.subscribeOn(Schedulers.io()) // RxJava方法,控制请求执行的线程

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Action1() { // 请求成功回调

@Override

public void call(WeatherBean weatherBean) {

onSuccess(weatherBean);

}

}, new Action1() { // 请求失败回调

@Override

public void call(Throwable throwable) {

onFail(throwble);

}

});

当然啦,你可能会觉得这还不够简洁,那么我们可以加入JDK1.8的Lambda表达式来简化代码的书写。

在Android Studio中使用Lambda表达式,需要JDK版本在1.8以上,并且在在Module下的build.gradle中进行相关配置

android {

...

defaultConfig {

...

jackOptions {

enabled true

}

}

...

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_8

targetCompatibility JavaVersion.VERSION_1_8

}

}

这样,就可以在代码中使用Lambda表达式了,实现的效果如下:

RXClientGenerator.getInstance().createClient()

.getWeather("0")

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(weatherBean -> onSuccess(weatherBean),

throwable -> onFail(throwble));

Interceptor

在前面,我们提到了一个NetInterceptor,这个类是一个拦截器,用来简化网络请求,并且可以打印出网络请求的详细信息,方便调试,不多说,看代码:

NetInterceptor.java

class NetInterceptor implements Interceptor { // 实现了OkHttp的Interceptor接口

private static final Charset UTF8 = Charset.forName("UTF-8");

private String versionName;

private String platform;

private String imei;

/**

* 构造方法

*/

NetInterceptor() {

versionName = BuildConfig.VERSION_NAME; // 版本名

platform = "android"; // 应用平台

imei = ""; 设备IMEI

}

@Override

public Response intercept(Chain chain) throws IOException {

Request oldRequest = chain.request(); // 在这里获取请求对象

// 添加新的参数

HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()

.newBuilder()

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

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

.addQueryParameter("version", versionName) // 这些是每个接口都必须有的请求参数,可以在这里添加

.addQueryParameter("platform", platform)

.addQueryParameter("imei", imei);

// 新的请求

Request request = oldRequest.newBuilder() // 添加完参数后,转换成新的请求

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

.url(authorizedUrlBuilder.build())

.build();

if (!BuildConfig.DEBUG) // 如果是正式环境,直接发送请求并返回

return chain.proceed(request);

// 获取请求数据

RequestBody requestBody = request.body();

boolean hasRequestBody = requestBody != null;

Connection connection = chain.connection();

Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;

StringBuilder sb = new StringBuilder(); // 使用StringBuilder,将所有数据拼接起来

sb.append("\n--> ").append(request.method()).append(" ").append(request.url()).append(" ").append(protocol);

if (hasRequestBody) {

sb.append(" (").append(requestBody.contentLength()).append("-byte body");

}

sb.append("\n");

if (hasRequestBody) {

if (requestBody.contentType() != null) {

sb.append("Content-Type: ").append(requestBody.contentType()).append("\n");

}

if (requestBody.contentLength() != -1) {

sb.append("Content-Length: ").append(requestBody.contentLength()).append("\n");

}

}

Headers headers = request.headers();

for (int i = 0, count = headers.size(); i < count; i++) {

String name = headers.name(i);

if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {

sb.append(name).append(": ").append(headers.value(i)).append("\n");

}

}

if (!hasRequestBody) {

sb.append("--> END ").append(request.method()).append("\n");

} else if (bodyEncoded(request.headers())) {

sb.append("--> END ").append(request.method()).append(" (encoded body omitted)").append("\n");

} else {

Buffer buffer = new Buffer();

requestBody.writeTo(buffer);

Charset charset = UTF8;

MediaType contentType = requestBody.contentType();

if (contentType != null) {

charset = contentType.charset(UTF8);

}

sb.append("\n");

sb.append(buffer.readString(charset)).append("\n");

sb.append("--> END ").append(request.method()).append(" (").append(requestBody.contentLength()).append("-byte body)").append("\n");

}

long startNs = System.nanoTime();

// 注意,这里为了打印出返回的数据,实际上是进行了一次请求,在开发中有的接口重复调用会出现数据重复问题,注意判断

Response response = chain.proceed(request);

long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);

ResponseBody responseBody = response.body();

long contentLength = responseBody.contentLength();

String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length";

sb.append("

.append(response.request().url()).append(" (").append(tookMs).append("ms, ")

.append(bodySize).append(" body)").append("\n");

Headers headers1 = response.headers();

for (int i = 0, count = headers1.size(); i < count; i++) {

sb.append(headers1.name(i)).append(": ").append(headers1.value(i)).append("\n");

}

if (!HttpEngine.hasBody(response)) {

sb.append("

} else if (bodyEncoded(response.headers())) {

sb.append("

} else {

BufferedSource source = responseBody.source();

source.request(Long.MAX_VALUE); // Buffer the entire body.

Buffer buffer = source.buffer();

Charset charset = UTF8;

MediaType contentType = responseBody.contentType();

if (contentType != null) {

try {

charset = contentType.charset(UTF8);

} catch (UnsupportedCharsetException e) {

sb.append("\n");

sb.append("Couldn't decode the response body; charset is likely malformed.").append("\n");

sb.append("

return response;

}

}

if (contentLength != 0) {

sb.append("\n");

String json = buffer.clone().readString(charset);

sb.append(json).append("\n\n");

String str = jsonFormat(json);

if (str.length() > 1200) {

String start = str.substring(0, 600);

String end = str.substring(str.length() - 600);

sb.append(start).append("\n")

.append("\nThe json was too long...\n\n")

.append(end).append("\n");

} else {

sb.append(str).append("\n");

}

}

sb.append("

}

Log.d("NET_INFO", sb.toString()); // 打印信息

return chain.proceed(request); // 发送请求并返回

}

private boolean bodyEncoded(Headers headers) {

String contentEncoding = headers.get("Content-Encoding");

return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");

}

/**

* 将json字符串格式化后返回

*

* @param json json字符串

* @return 格式化后的字符串

*/

private String jsonFormat(String json) {

if (TextUtils.isEmpty(json)) {

return "Empty/Null json content";

}

try {

json = json.trim();

String message;

if (json.startsWith("{")) {

JSONObject jsonObject = new JSONObject(json);

message = jsonObject.toString(2);

return message;

} else if (json.startsWith("[")) {

JSONArray jsonArray = new JSONArray(json);

message = jsonArray.toString(2);

return message;

} else {

message = "Invalid Json";

}

return message;

} catch (JSONException e) {

Log.e("JSON_ERROR", e.getMessage());

return "Invalid Json";

}

}

}

怎么样,是不是又新学到了一招,今天就讲到这里了,欢迎大家指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值