您的位置:首页 > 理论基础 > 计算机网络

Retrofit+okhttp3的简单封装实现网络请求和拦截

2017-04-28 09:55 417 查看
项目开发中经常会遇到这样的需求,就是我想知道当前请求的url是什么样的?以便后台开发人员和客户端人员更好的找到错误。这篇博客着重介绍的就是简单的封装retrofit和okhttp3实现网络请求以及使用okhttp3的拦截器功能实现拦截客户端发送到服务器上的url。

添加依赖

在module中build.gradle中添加

compile 'com.squareup.retrofit2:retrofit:2.1.0'

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

compile 'com.squareup.okhttp3:logging-interceptor:3.4.0-RC1'


其中compile ‘com.squareup.okhttp3:logging-interceptor:3.4.0-RC1就是为了实现拦截器功能

初始化retrofit

private void initRetrofit() {
if (null == mRetrofit) {
initOkHttpClient();

GsonBuilder gsonBuilder = new GsonBuilder();

// Gson double类型转换, 避免空字符串解析出错
final TypeAdapter<Number> DOUBLE = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
if (in.peek() == JsonToken.STRING) {
String tmp = in.nextString();
if (TextUtils.isEmpty(tmp)) tmp = "0";
return Double.parseDouble(tmp);
}
return in.nextDouble();
}

@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};

// Gson long类型转换, 避免空字符串解析出错
final TypeAdapter<Number> LONG = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
if (in.peek() == JsonToken.STRING) {
String tmp = in.nextString();
if (TextUtils.isEmpty(tmp)) tmp = "0";
return Long.parseLong(tmp);
}
return in.nextLong();
}

@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};

// Gson int类型转换, 避免空字符串解析出错
final TypeAdapter<Number> INT = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
if (in.peek() == JsonToken.STRING) {
String tmp = in.nextString();
if (TextUtils.isEmpty(tmp)) tmp = "0";
return Integer.parseInt(tmp);
}
return in.nextInt();
}

@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};

gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(double.class, Double.class, DOUBLE));
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(long.class, Long.class, LONG));
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(int.class, Integer.class, INT));

mRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(mOkHttpClient) //设置okhttp
.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
}


上面的代码浅显易懂,只是使用了Gson对几种常见类型转换, 避免空字符串解析出错以及设置okhttp

初始化okhttp

private void initOkHttpClient() {
if (null == mOkHttpClient) {

OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (builder.interceptors() != null) {

4000
builder.interceptors().clear();
}
//设置超时
builder.connectTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS);
builder.readTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS);
builder.writeTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.SECONDS);
//错误重连
builder.retryOnConnectionFailure(true);

//DEBUG模式下配Log拦截器
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(loggingInterceptor);
}

//            builder.addNetworkInterceptor();

if (Configuration.isShowNetworkParams()) {
builder.addInterceptor(new LoggingInterceptor());
}
mOkHttpClient = builder.build();
}
}


这段代码主要设置连接超时以及添加一个拦截器

初始化拦截器

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

Request request = chain.request();
long t1 = System.nanoTime();

Buffer buffer = new Buffer();
if (request.body() != null)
request.body().writeTo(buffer);

KLog.e( String.format("Sending request %s on %s%n%sRequest Params: %s",
request.url(), chain.connection(), request.headers(), buffer.clone().readUtf8()));
buffer.close();

Response response = chain.proceed(request);
long t2 = System.nanoTime();

BufferedSource source = response.body().source();
source.request(Long.MAX_VALUE);
buffer = source.buffer().clone();
KLog.e(String.format("Received response for %s%nin %.1fms%n%sResponse Json: %s",
response.request().url(), (t2 - t1) / 1e6d, response.headers(),
buffer.readUtf8()));
buffer.close();

return response;
}


Interceptor 接口只包含一个方法 intercept,其参数是 Chain 对象。Chain 对象表示的是当前的拦截器链条。通过 Chain 的 request 方法可以获取到当前的 Request 象。Responseresponse=chain.proceed(request); 这个很重要,它是将我们拦截器串联起来的关键,我们在实现拦截器的时候,需要返回一个response,就是调用该方法,添加请求头啊,什么的才能被执行

调用retrofit

private HttpHelper() {
initRetrofit();
}
//获取单例
public static HttpHelper getInstance() {
if (INSTANCE == null) {
synchronized (HttpHelper.class) {
if (INSTANCE == null) {
INSTANCE = new HttpHelper();
}
}
}
return INSTANCE;
}
public ApiService initService() {
return mRetrofit.create(ApiService.class);
}


其中ApiService 就是我们声明所有的联网请求的接口,至此对retrofit和okhttp的封装全部完成
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息