android中Retrofit2.0的封装:设计到请求前后的操作,比如添加请求头,拦截请求头,拦截返回体等

这里关于android如何集成retrofit2.0就详细介绍了,相信网络上也有很多的例子。

首先retrofit关于请求体如何加入的话,这里使用注解就能解决大部分问题,而retrofit官网也给出了很多很好用的注解,只要在interface中声明就行。

主要使用分为以下例子:

①添加retrofit库依赖

②创建接受请求数据bean

③创建用于请求的接口

④创建retrofit实例

⑤创建网络请求接口实例以及配置网络请求参数

⑥发送网络请求

⑦处理返回数据

 

主要从第四步讲起:

常规的retrofit实例创建是新建一个Builder()

比如:

Retrofit retrofit =new Retrofit.Builder()
.baseUrl(“www.XXXXXX”)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();

这是常规创建实例,而我们知道,retrofit是基于okhttp的网络请求框架,所以我们封装的时候,可以写一个公有类,以下这是我的做法。

public class RetrofitHelper  {
    /** 连接超时:10秒 */
    public static final int TIME_OUT_CONNECT = 10 * 1000;

    /** 读数据超时:10秒 */
    public static final int TIME_OUT_READ = 10 * 1000;

    /** 转换日志输出格式 */
    private static HttpLoggingInterceptor.Logger mLogger = new MyHttpLogger();

    private static OkHttpClient mOkHttpClient;

    //cookie存储
    public static ConcurrentHashMap> cookieStore;


    /**
     * 获取带有json转换器的Retrofit对象,如果不需要json转换器请使用
     * buildRetrofit(String baseUrl, boolean isNeedGsonConverter)方法获取
     *
    
     */
    public static Retrofit buildRetrofit(String baseUrl) {
        return buildRetrofit(baseUrl, true);
    }

    /**
     * 构建统一封装的Retrofit对象
     *
     * @param baseUrl
     * @param isNeedGsonConverter 是否需要gson转换器
     * @return Retrofit对象
     */
    public static Retrofit buildRetrofit(String baseUrl, boolean isNeedGsonConverter) {
        Retrofit.Builder builder = new Retrofit.Builder()
            .client(getSingleOkHttpClient())
            .baseUrl(baseUrl);
        if (isNeedGsonConverter) {
            builder.addConverterFactory(GsonConverterFactory.create());
        }
        return builder.build();
    }

    /**
     * 获取OkHttpClient对象,用于需要定制OkHttpClient的情况。
     * 该对象已经做了基本的封装,使用者可以在此基础上做进一步定制。
     * 用法:
     * Retrofit retrofit = RetrofitHelper.buildRetrofit("baseUrl");
     * OkHttpClient okHttpClient = RetrofitHelper.getmOkHttpClient();
     * ... // 对okHttpClient做一些个性化定制
     * retrofit = retrofit.newBuilder().client(okHttpClient).build(); //重新设置定制好的client
     * ... //继续后续操作
     * 

* 通常情况下不需要获取OkHttpClient对象,直接使用buildRetrofit()方法返回的Retrofit对象即可。 * * @return */ public static OkHttpClient getmOkHttpClient() { return buildClient(); } /** * 获取单例的okHttpClient对象 * * @return */ private synchronized static OkHttpClient getSingleOkHttpClient() { if (mOkHttpClient == null) { mOkHttpClient = buildClient(); } return mOkHttpClient; } /** * 构建统一封装的OkHttpClient对象, * 该对象增加了日志拦截器及连接超时等参数 * * @return */ private static OkHttpClient buildClient() { // 日志拦截器 HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(mLogger); if(cookieStore==null){ cookieStore = new ConcurrentHashMap<>(); } logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient().newBuilder() .connectTimeout(TIME_OUT_CONNECT, TimeUnit.MILLISECONDS) .readTimeout(TIME_OUT_READ, TimeUnit.MILLISECONDS) .cookieJar(new CookieJar() { //cookie拦截保存 @Override public void saveFromResponse(HttpUrl url, List cookies) { BaseActivity.setCookies(cookies); Log.i("状态","Cookie保留成功"); Log.i("cooike为",BaseActivity.getCookies().toString()); } @Override public List loadForRequest(HttpUrl url) { Log.i("cooike为",BaseActivity.getCookies().toString()); Log.i("状态","Cookie发送"); return BaseActivity.getCookies(); } }) .addNetworkInterceptor(logInterceptor); return builder.build(); } /** * 将http报文中的json字符串格式化并使用com.orhanobut.logger.Logger日志系统打印日志的类 * */ private static class MyHttpLogger implements HttpLoggingInterceptor.Logger { StringBuilder mMessage = new StringBuilder(); @Override public void log(String message) { // 打印请求或者响应报文中的每一行都会调用此方法,所以用一个StringBuilder把它们串起来 // 以{}或者[]形式的说明是响应结果的json数据,需要进行格式化 boolean isJsonStr = (message.startsWith("{") && message.endsWith("}")) || (message.startsWith("[") && message.endsWith("]")); if (isJsonStr) { message = CommonUtils.formatJsonString(message); } mMessage.append(message.concat("\n")); // 响应结束,打印整条日志 if (message.startsWith("<-- END HTTP")) { Logger.d(mMessage.toString()); Logger.d("我是小尾巴"); mMessage.setLength(0); } } } }

接下来是对这个基础类的讲解,首先声明的是几个限制常量,用在okhttp中的超时设置中。接着是日志打印,我后面在发送请求的时候都会打印出来请求体与返回体,接着是一个cookie的存储,坑爹的是因为后台框架使用的是给WEB用的,登录状态用的是session来保存,后续请求也都是,所以在这里我将第一次登录获取到的session保存起来并在后面需要的时候就使用上。后面我在建立实例的时候,设置选择与不选择gson转换器的模式。

接下来讲的就是重点:

new一个retrofitbuilder的时候会设置client,这里我将client专门拿出来定制

/**
 * 构建统一封装的OkHttpClient对象,
 * 该对象增加了日志拦截器及连接超时等参数
 *
 * @return
 */
private static OkHttpClient buildClient() {
    // 日志拦截器
    HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(mLogger);

    if(cookieStore==null){
        cookieStore = new ConcurrentHashMap<>();
    }

    logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
        .connectTimeout(TIME_OUT_CONNECT, TimeUnit.MILLISECONDS)
        .readTimeout(TIME_OUT_READ, TimeUnit.MILLISECONDS)
            .cookieJar(new CookieJar() {                    //cookie拦截保存
                @Override
                public void saveFromResponse(HttpUrl url, List cookies) {
                    BaseActivity.setCookies(cookies);
                    Log.i("状态","Cookie保留成功");
                    Log.i("cooike为",BaseActivity.getCookies().toString());
                }

                @Override
                public List loadForRequest(HttpUrl url) {
                    Log.i("cooike为",BaseActivity.getCookies().toString());
                    Log.i("状态","Cookie发送");
                    return BaseActivity.getCookies();
                }
            })
                 .addNetworkInterceptor(logInterceptor);
    return builder.build();
}

在这上面我们设置了超时限制,以及cookie的保存以及cookie的发送。

以上是对okhttp的一些修饰

接下来我要讲的是关于retrofit返回状态码的拦截,主要操作的是第六步,发送网络请求的时候。

常规操作是这样的:

//发送异步请求

Call.enqueue(new Callback(){
		//成功时回调
	Public void onResponse(Call call,Response response){
		Response.body().show();
	  }
		//失败时回调
	Public void onFailure(Call call,Throwable throwable) {
		System.out.println(“连接失败”);
	  }
	});

以上是我们的常规做法,直接使用已有的callback类

我实现的方法是使用自定义的Callback并接入callback接口类。

首先先定义自己的callback:

package com.b2bwings.framework.network;

import android.util.Log;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by xuweijie
 * on 2018/7/16 0016.
 */
public final class MyCallBack implements Callback {
    /** 公共事务处理器 */
    private static ICommonProcessor processor;

    /** 网络请求回调接口 */
    private LoadDataCallBack loadDataCallBack;

    public MyCallBack(LoadDataCallBack loadDataCallBack) {
        this.loadDataCallBack = loadDataCallBack;
    }

    @Override
    public void onFailure(Call call, Throwable t) {
        // 这里可以对错误做统一的处理,目前只输出错误日志,子类可以重写此方法作进一步处理
        String url = call.request().url().toString();
       
    }

    @Override
    public void onResponse(Call call, Response response) {
        switch (response.code()) {
            case 401:
                // 401 代表登录失效(登录session失效)
                if (processor != null) {
                    Log.d("状态","统一处理401错误");
                    processor.process401();
                } else {
                    Log.w("状态","401错误,未设置公共处理器");
                }
                return;

            //暂未设置错误码拦截器
            default:
                break;
        }
        loadDataCallBack.onSuccess(response);
    }

    /**
     * 设置公共处理器
     *
     * @param iCommonProcessor
     */
    public static void setCommonProcessor(ICommonProcessor iCommonProcessor) {
        processor = iCommonProcessor;
    }
}

以及拦截接口

/**
 * Created by xuweijie
 * on 2018/7/13 0013.
 */
public interface ICommonProcessor {
    /**
     * 处理401错误,即登录失效
     */
    void process401();
}

//加载数据回调接口

public interface LoadDataCallBack {
    /**
     * 加载数据成功
     *
     * @param response 返回的数据
     */
    void onSuccess(Response response);

    /**
     * 加载数据失败
     *
     * @param throwable 错误信息
     */
    void onError(Throwable throwable);
}

 

其中在onResponse响应中,处理完拦截器之后就会回调onSuccedd回调。

以上是进行了状态码401的拦截。

最后要注意的是,必须在使用到拦截器的地方的进行设置

即:

MyCallBack.setCommonProcessor(this);

 

以上就是我对retrofit的一些封装,实现了返回提中cookie的拦截,以及返回体状态码的统一处理。

 

如果大家有什么疑问或者意见,欢迎批评指正


你可能感兴趣的:(android)