Android:封装网络请求库Volley结合Okhttp

1. 前言

在拷贝Github的源码到本地时,有一个技巧,能节约很多修改package和import的时间

  1. 在Github下载源码的zip包到本地,解压
  2. 将下载的源码的java目录下的文件夹全部拷贝到目标位置的java目录下
  3. 修复一些第三方依赖的问题
  4. 再将目标位置的java目录下的包名整体移动到希望的包下面

这样做的好处时,让编辑器自动完成包名和导包的替换,不用手动替换。

2. 为什么要volley结合okhttp

okhttp是非常优秀的网络请求库,网络传输层非常好用,支持http和https,被google官方接受,但只是单纯的网络操作工具,没有封装异步操作。而volley是google推出的,可以取消请求,有请求缓存功能,在高并发且数据量小的场景非常适合,但是在大数据量请求表现糟糕,并且不支持https。因此将这两种结合起来,采用volley的高并发调度和缓存功能,采用okhttp网络传输功能。

3. 结合volley和okhttp的步骤

volley把网络传输层通过HttpStack接口的方式暴露出来,因此可以实现这个接口来替换Volley默认的网络传输层的实现

整个网络请求的流程:

  1. 首先将volley的Request转换为okhttp的Request
  2. 调用okhttp的网络传输层,将okhttp的Request转换为okhttp的Response
  3. 将okhttp的Response转换为apache的Response
  4. 将apache的Response转换为volley的Response

整合volley和okhttp的步骤:

  1. 实现OkHttpHelper类,将okhttp的网络操作封装一下
  2. 实现OkHttpInterceptor类,用于输出请求和返回的日志
  3. 实现OkHttpStack类,实现volley的HttpStack接口。内部主要完成:解析和处理volley的request的header、解析和处理volley的request的body、将volley的request的header和body设置到okhttp的request上、用okhttp传输网络层得到okhttp的response、解析okhttp的response的header、解析okhttp的response的body、将okhttp的response的header和body设置到apache的HttpResponse上。
  4. 实现HeaderStorage类,将请求的header数据(包括cookie数据)缓存起来
  5. 实现CookieStorage类,将请求的header中的cookie数据和返回的cookie数据缓存起来,供下次请求使用
  6. 实现CustomDiskCache类,指定volley的硬盘缓存策略
  7. 实现SecurityUtil类,解决okhttp的https证书校验问题
  8. 实现BaseCustomJsonRequest类和其子类CustomJsonObjectRequest和CustomJsonArrayRequest类,内部兼容json类型的请求数据和form表单类型的请求数据。
  9. 实现CustomJsonBody类,继承了RequestBody类,封装json数据的string类型转换为okhttp接受的RequestBody类型。
  10. 实现NetworkConfig类,完成整个网络库所提供对外的所有配置,包括超时时间、连接池数量、域名设置等等
  11. 实现NetworkLogger类,完成网络库关键数据的打印功能
  12. 实现NetworkManager类,内部实现网络库的初始化,已经网络请求的添加。这个类是暴露给外部使用的
  13. okhttp源码的一些修改,okhttp不只是针对android平台的,因此其源码设计具有移植性。所以需要稍微改动使其支持android平台

4. 关键位置讲解

因为代码较多,不可能全部都拿来讲,因此这里只把关键的一个地方讲一下,其他地方可查阅源代码

首先导入volley和okhttp所需要的依赖

apply plugin: 'com.android.library'

android {
    compileSdkVersion 28
    /* volley依赖,这个是为了在android 6.0以上的高版本引用HttpClient*/
    useLibrary 'org.apache.http.legacy'


    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    /* okhttp依赖 */
    implementation 'com.squareup.okio:okio:1.14.0'
    implementation 'com.google.code.findbugs:jsr305:2.0.1'
    implementation 'org.conscrypt:conscrypt-openjdk-uber:1.1.3'
}

OkHttpHelper封装了okhttp的网络操作,使其所有操作共享一个连接池

public class OkHttpHelper {

    private static OkHttpClient mClientHttp = null;
    private static OkHttpClient mClientHttps = null;

    private final static Object clientHttpLock = new Object();
    private final static Object clientHttpsLock = new Object();

    private final static CustomCookieJar mCookieJar = new CustomCookieJar();

    private static OkHttpClient getClientHttp() {
        return getClientHttp(0);
    }

    private static OkHttpClient getClientHttp(int timeOut) {
        if (mClientHttp == null) {
            synchronized (clientHttpLock) {
                if (mClientHttp == null) {
                    mClientHttp = getBuilder(false, timeOut).build();
                }
            }
        }
        return mClientHttp;
    }

    private static OkHttpClient getClientHttps() {
        return getClientHttps(0);
    }

    private static OkHttpClient getClientHttps(int timeOut) {
        if (mClientHttps == null) {
            synchronized (clientHttpsLock) {
                if (mClientHttps == null) {
                    mClientHttps = getBuilder(true, timeOut).build();
                }
            }
        }
        return mClientHttps;
    }

    public static OkHttpClient getClient(boolean isHttps) {
        return getClient(isHttps, 0);
    }

    public static OkHttpClient getClient(boolean isHttps, int timeOut) {
        if (isHttps) {
            return getClientHttps(timeOut);
        } else {
            return getClientHttp(timeOut);
        }
    }

    private static OkHttpClient.Builder getBuilder(boolean isHttps, int timeOut) {
        NetworkConfig config = NetworkManager.getInstance().getNetworkConfig();

        int readTimeOut = config.getReadTimeout() / 1000;
        int writeTimeOut = config.getWriteTimeout() / 1000;
        int connTimeOut = config.getConnTimeout() / 1000;

        if (timeOut > 0) {
            timeOut = timeOut / 1000; //转换成 秒
            connTimeOut = timeOut;
            readTimeOut = timeOut;
            writeTimeOut = timeOut;
        }

        OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
                .readTimeout(readTimeOut, TimeUnit.SECONDS)
                .writeTimeout(writeTimeOut, TimeUnit.SECONDS)
                .connectTimeout(connTimeOut, TimeUnit.SECONDS)
                .cookieJar(mCookieJar);

        if (isHttps) {
            SSLSocketFactory sslSocketFactory = SecurityUtil.getSSLSocketFactory();
            if (null != sslSocketFactory) {
                builder.sslSocketFactory(sslSocketFactory);
            }
            builder.hostnameVerifier(SecurityUtil.getHostnameVerifier());
        }

        builder.addInterceptor(new OkHttpInterceptor());
        return builder;
    }
}

OkHttpInterceptor只要用于okhttp请求和返回的日志打印

/**
 * okhttp拦截器,用于日志打印
 */
public class OkHttpInterceptor implements Interceptor {

    private static final String NEWLINE = "\n";

    @Override
    public Response intercept(Chain chain) throws IOException {
        long requestTime = System.currentTimeMillis();
        Request request = chain.request();

        StringBuilder sb = new StringBuilder();
        sb.append("请求url为:").append(request.url()).append(NEWLINE);
        sb.append("请求方式为:").append(request.method()).append(NEWLINE);

        // 打印请求的header
        Headers requestHeaders = request.headers();
        sb.append(handleHeader(requestHeaders, true)).append(NEWLINE);
        // 打印请求内容
//        if (!request.method().toLowerCase().contains("get")) {
        RequestBody rb = request.body();
        if (rb != null) {
            okio.Buffer buffer = new okio.Buffer();
            rb.writeTo(buffer);
            sb.append("请求的数据为:").append(buffer.readUtf8()).append(NEWLINE);
            buffer.clear();
        }
//        }

        Response response = chain.proceed(request);
        // 打印返回的header
        Headers responseHeaders = response.headers();
        sb.append(handleHeader(responseHeaders, false)).append(NEWLINE);
        // 打印返回内容
        String content = response.body().string();
        long responseTime = System.currentTimeMillis();
        sb.append("HTTP状态码:").append(response.code()).append(NEWLINE);
        sb.append("耗费时间为:").append(responseTime - requestTime).append("ms").append(NEWLINE);
        sb.append("返回的数据为:").append(content).append(NEWLINE);
        NetworkLogger.d(sb.toString());
        MediaType mediaType = response.body().contentType();
        return response.newBuilder().body(ResponseBody.create(mediaType, content)).build();
    }

    private String handleHeader(Headers headers, boolean isRequest) {
        Iterator<String> iterator = headers.names().iterator();
        StringBuilder headerString = new StringBuilder();
        headerString.append(isRequest ? "请求的header为:" : "返回的header为:");
        while (iterator.hasNext()) {
            String name = iterator.next();
            List<String> headerValues = headers.values(name);
            headerString.append("[").append(name).append(":").append(headerValues.isEmpty() ? "" : headerValues.get(0)).append("]");
        }
        return headerString.toString();
    }
}

OkHttpStack将volley的网络传输层实现交由okhttp完成,最后返回apache的response

public class OkHttpStack implements HttpStack {

    @Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {

        String originUrl = request.getUrl();
        Uri uri = Uri.parse(originUrl);

        boolean isHttps = false;
        if (uri.getScheme().toLowerCase().equals("https")) {
            isHttps = true;
        }

        // 2017/12/8  可以单独给 一个请求设置超时时间,具体参考 单元测试
        int timeout = request.getRetryPolicy().getCurrentTimeout();
        if (timeout == DefaultRetryPolicy.DEFAULT_TIMEOUT_MS) {
            // 2017/12/8  如果这里时间等于 volley 的默认时间,那么不应该手动设置超时时间,应该用 OkHttp 全局的。
            timeout = -1;
        }

        OkHttpClient client = OkHttpHelper.getClient(isHttps, timeout);
        com.hyperion.networklib.okhttp3.Request.Builder requestBuilder = new com.hyperion.networklib.okhttp3.Request.Builder();

        // 解析请求中的header和默认携带的header和内存中的cookie
        parseRequestHeader(requestBuilder, request);
        // 解析请求的数据
        parseRequestBody(requestBuilder, request);

        // 交由okhttp执行网络传输层
        com.hyperion.networklib.okhttp3.Request okhttp3Request = requestBuilder.url(uri.toString()).build();
        Response okHttpResponse = client.newCall(okhttp3Request).execute();

        // 解析返回数据的状态码
        StatusLine responseStatus = new BasicStatusLine(
                parseProtocol(okHttpResponse.protocol()),
                okHttpResponse.code(),
                okHttpResponse.message()
        );
        BasicHttpResponse response = new BasicHttpResponse(responseStatus);
        // 解析返回的header
        parseResponseHeader(response, okHttpResponse);
        // 解析返回的数据
        parseResponseBody(response, okHttpResponse);

        return response;
    }


    private void parseRequestHeader(com.hyperion.networklib.okhttp3.Request.Builder builder, Request<?> request)
            throws IOException, AuthFailureError {
        Map<String, String> headers = request.getHeaders();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    private void parseRequestBody(com.hyperion.networklib.okhttp3.Request.Builder builder, Request<?> request)
            throws IOException, AuthFailureError {
        switch (request.getMethod()) {
            case Request.Method.DEPRECATED_GET_OR_POST:
                builder.post(createGetBody(request));
                break;

            case Request.Method.GET:
                builder.get();
                break;

            case Request.Method.DELETE:
                builder.delete();
                break;

            case Request.Method.POST:
                RequestBody requestBody = createPostBody(request);
                if (requestBody != null) {
                    builder.post(requestBody);
                }
                break;

            case Request.Method.PUT:
                builder.put(createGetBody(request));
                break;

            case Request.Method.HEAD:
                builder.head();
                break;

            case Request.Method.OPTIONS:
                builder.method("OPTIONS", null);
                break;

            case Request.Method.TRACE:
                builder.method("TRACE", null);
                break;

            case Request.Method.PATCH:
                builder.patch(createGetBody(request));
                break;

            default:
                throw new IllegalStateException("Unknown method type.");
        }
    }

    private RequestBody createGetBody(Request request)
            throws AuthFailureError {
        final byte[] body = request.getBody();
        return RequestBody.create(MediaType.parse(request.getBodyContentType()), body);
    }

    private RequestBody createPostBody(Request request) throws AuthFailureError {
        RequestBody requestBody = null;
        if (request instanceof BaseCustomJsonRequest) {
            BaseCustomJsonRequest customJsonRequest = (BaseCustomJsonRequest) request;
            requestBody = customJsonRequest.getRequestBody();
        }else{
            requestBody = RequestBody.create(MediaType.parse(request.getBodyContentType()), request.getBody());
        }
        return requestBody;
    }

    private ProtocolVersion parseProtocol(final Protocol protocol) {
        switch (protocol) {
            case HTTP_1_0:
                return new ProtocolVersion("HTTP", 1, 0);
            case HTTP_1_1:
                return new ProtocolVersion("HTTP", 1, 1);
            case SPDY_3:
                return new ProtocolVersion("SPDY", 3, 1);
            case HTTP_2:
                return new ProtocolVersion("HTTP", 2, 0);
        }

        throw new IllegalAccessError("Unkwown protocol");
    }

    private void parseResponseHeader(BasicHttpResponse httpResponse, Response response) {
        Headers responseHeaders = response.headers();
        if (responseHeaders != null) {
            for (int i = 0, len = responseHeaders.size(); i < len; i++) {
                final String name = responseHeaders.name(i);
                final String value = responseHeaders.value(i);
                if (name != null) {
                    httpResponse.addHeader(new BasicHeader(name, value));
                }
            }
        }
    }

    private void parseResponseBody(BasicHttpResponse httpResponse, Response response) throws IOException {
        BasicHttpEntity entity = new BasicHttpEntity();
        ResponseBody body = response.body();
        entity.setContentLength(body.contentLength());

        String encoding = response.header("Content-Encoding");
        if (!TextUtils.isEmpty(encoding) && encoding.equals("gzip")) {
            entity.setContent(new GZIPInputStream(body.byteStream()));
        } else {
            entity.setContent(body.byteStream());
        }
        entity.setContentEncoding(encoding);

        if (body.contentType() != null) {
            entity.setContentType(body.contentType().type());
        }
        httpResponse.setEntity(entity);
    }

}

BaseCustomJsonRequest封装的兼容form和json请求

/**
 * 封装的即可传递json,也可传递form
 */
public abstract class BaseCustomJsonRequest<T> extends JsonRequest<T> {

    private Map<String, String> formBody;
    private Map<String, String> headers;
    private Charset charset = Charset.UTF8;

    /**
     * 请求json数据
     */
    public BaseCustomJsonRequest(int method, String url, String requestBody,
                                 Listener<T> listener, ErrorListener errorListener) {
        super(method, url, requestBody, listener, errorListener);
    }

    /**
     * 请求表单数据
     */
    public BaseCustomJsonRequest(int method, String url, Map<String, String> requestMap,
                                 Listener<T> listener, ErrorListener errorListener) {
        super(method, url, "", listener, errorListener);
        formBody = requestMap;
    }

    public Map<String, String> getFormBody() {
        return formBody;
    }

    public void setFormBody(Map<String, String> formBody) {
        this.formBody = formBody;
    }

    public Charset getCharset() {
        return charset;
    }

    public void setCharset(Charset charset) {
        this.charset = charset;
    }

    public void setHeaders(Map<String, String> headers) {
        this.headers = headers;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        if (headers == null || headers.isEmpty()) {
            headers = new HashMap<>();
        }
        headers.putAll(HeaderUtil.getRequestHeader(this));
        return headers;
    }

    public RequestBody getRequestBody() throws AuthFailureError {
        RequestBody bodyRes = null;
        Map<String, String> postBody = getFormBody();
        //在使用CustomJsonRequest的时候,如果设置了postBody,那么就直接从map取值,否则,使用json字符串方式
        if (postBody == null) {
            final byte[] body = getBody();
            if (body == null) return null;
            CustomJsonBody.Builder jsonBuilder = new CustomJsonBody.Builder();
            String bodyStr = null;
            try {
                BaseCustomJsonRequest.Charset set = getCharset();
                bodyStr = new String(body, BaseCustomJsonRequest.Charset.UTF8.getValue());
                jsonBuilder.setRequstBodyCharset(set);
                jsonBuilder.setJson(bodyStr);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            bodyRes = jsonBuilder.build();
        } else {
            FormBody.Builder formBodyBuilder = new FormBody.Builder();
            for (Map.Entry<String, String> entry : postBody.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (value != null) {
                    formBodyBuilder.add(key, value);
                }
            }
            bodyRes = formBodyBuilder.build();
        }
        return bodyRes;
    }

    public enum Charset {

        UTF8("UTF-8"),
        ISO("ISO-8859-1");

        String value;

        Charset(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }
    }
}

NetworkManager实现网络库的初始化以及添加一个新的网络请求

public class NetworkManager {

    private volatile static NetworkManager instance;

    private Context mContext;
    private NetworkConfig mNetworkConfig;
    private HeaderStorage headerStorage;
    private CookieStorage cookieStorage;
    private CustomDiskCache diskCache;
    private RequestQueue requestQueue;

    private NetworkManager() {
        cookieStorage = new CookieStorage();
        headerStorage = new HeaderStorage(cookieStorage);
    }

    public static NetworkManager getInstance() {
        if (instance == null) {
            synchronized (NetworkManager.class) {
                if (instance == null) {
                    instance = new NetworkManager();
                }
            }
        }
        return instance;
    }

    public Context getContext() {
        return mContext;
    }

    public NetworkConfig getNetworkConfig() {
        return mNetworkConfig;
    }

    public HeaderStorage getHeaderStorage() {
        return headerStorage;
    }

    public CookieStorage getCookieStorage() {
        return cookieStorage;
    }

    public CustomDiskCache getDiskCache() {
        return diskCache;
    }

    public void init(Context context, NetworkConfig config) {
        if (context == null) {
            throw new IllegalStateException("Context cannot be null");
        }
        mContext = context.getApplicationContext();
        mNetworkConfig = config;
        if (mNetworkConfig == null) {
            mNetworkConfig = new NetworkConfig();
        }

        clearStorage();
        setHeaders(mNetworkConfig.getHeader());

        diskCache = new CustomDiskCache();
        OkHttpStack httpStack = new OkHttpStack();
        BasicNetwork network = new BasicNetwork(httpStack);
        requestQueue = new RequestQueue(diskCache.getBasedCache(), network, mNetworkConfig.getWorkerNumber());
        requestQueue.start();
    }

    public void clearStorage() {
        headerStorage.clear();
        cookieStorage.clear();
    }

    private void clearDisk() {
        ClearCacheRequest ccr = new ClearCacheRequest(diskCache.getBasedCache(), new Runnable() {
            @Override
            public void run() {

            }
        });
        requestQueue.add(ccr);
    }

    public void setHeaders(@NonNull Map<String, String> headers) {
        headerStorage.setHeaders(headers, true);
    }

    public void addHeaders(@NonNull Map<String, String> headers) {
        headerStorage.setHeaders(headers, false);
    }

    public Map<String, String> getHeaders() {
        return headerStorage.getHeaders();
    }

    public void updateCookie(Map<String, String> cookies) {
        cookieStorage.updateCookies(cookies);
    }

    public void addCookie(@NonNull String key, @NonNull String value) {
        cookieStorage.updateCookie(key, value);
    }

    public Map<String, String> getCookies() {
        return cookieStorage.getCookies();
    }

    public void cancel(@Nullable Object tag) {
        if (requestQueue != null) {
            requestQueue.cancelAll(tag);
        }
    }

    public void cancel(@NonNull RequestQueue.RequestFilter filter) {
        if (requestQueue != null) {
            requestQueue.cancelAll(filter);
        }
    }

    public void add(@NonNull Request req) {
        if (mContext == null) {
            throw new IllegalStateException("must invoke init method first");
        }

        //检查一下URL部分
        Uri uri = null;
        try {
            uri = Uri.parse(req.getUrl());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (uri == null) {
            NetworkLogger.e("the uri of request is Empty");
            return;
        }

        //检查一下是否是从允许的request中集成进来的
        if (!(req instanceof BaseCustomJsonRequest) && mNetworkConfig.isMustSpecifiedRequest()) {
            NetworkLogger.e("must add a BaseCustomJsonRequest");
            return;
        }

        String scheme = uri.getScheme().toLowerCase();
        if (!scheme.equals("https") && !scheme.equals("http")) {
            NetworkLogger.e("only support http or https");
            return;
        }

        RetryPolicy rp = req.getRetryPolicy();
        if (rp == null || (rp instanceof DefaultRetryPolicy && rp.getCurrentTimeout() ==
                DefaultRetryPolicy.DEFAULT_TIMEOUT_MS && rp.getCurrentRetryCount() ==
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES)) {
            //如果没有自定义的RP,那么就使用默认的处理
            req.setRetryPolicy(new CustomRetryPolicy());
        }
        requestQueue.add(req);
    }

    /**
     * 检查网络是否可用
     *
     * @return true:可用;false:不可用
     */
    public boolean checkNetworkAvaiable() {
        if (mContext == null) {
            throw new IllegalStateException("must invoke init method first");
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService
                (Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo == null) {
            return false;
        }
        return networkInfo.isAvailable();
    }
}

5. 对okhttp源码的修改

okhttp的源码给了三个目录

  • java:存放源代码的目录,但是缺一个Version类
  • java-templates:存放上面所缺的Version类
  • resources:存放域名检查相关的附件

第一个改动,将java-templates目录下的Version类,放入源码的okhttp3.internal目录下,并稍加改动,主要就是指定okhttp3的版本。版本从github主页上找,当前我的版本是3.11.0

public final class Version {
  public static String userAgent() {
    //return "okhttp/${project.version}";
    return "okhttp/3.11.0";
  }

  private Version() {
  }
}

第二个改动,将resources下的okhttp3.pro文件内容复制到当前module的proguard-rules.pro

# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**

# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*

# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform

第三个改动,将resources下的publicsuffixes.gz文件放入assets下,并且重命名为publicsuffixes(否则会出现FileNotFoundException),然后找到PublicSuffixDatabase类,改动两处代码。为了适配okhttp在android上读取附件的功能

// public static final String PUBLIC_SUFFIX_RESOURCE = "src/publicsuffixes.gz";
public static final String PUBLIC_SUFFIX_RESOURCE = "publicsuffixes";
// InputStream resource = PublicSuffixDatabase.class.getResourceAsStream(PUBLIC_SUFFIX_RESOURCE);
InputStream resource = NetworkManager.getInstance().getContext().getAssets().open(PUBLIC_SUFFIX_RESOURCE);

第四个改动,由于有些接口返回的domain和url不匹配导致接口会进行校验,此时加了一个配置开关forceIgnoredomain,可以强制不检验domain

// cc 强制忽略域名检查
boolean forceIgnoredomain = NetworkManager.getInstance().getNetworkConfig().isForceIgnoreCookieDomainCheck();
// If the domain is present, it must domain match. Otherwise we have a host-only cookie.
String urlHost = url.host();
if (domain == null) {
    domain = urlHost;
} else if (!forceIgnoredomain && !domainMatch(urlHost, domain)) {
    return null; // No domain match? This is either incompetence or malice!
}

// If the domain is a suffix of the url host, it must not be a public suffix.
if (!forceIgnoredomain) {
    if (urlHost.length() != domain.length()
            && PublicSuffixDatabase.get().getEffectiveTldPlusOne(domain) == null) {
        return null;
    }
}

6. 使用

首先在Application中进行初始化

private void initNetworkModule(){
    Map<String, String> headers = new HashMap<>();
    headers.put("time", System.currentTimeMillis() + "");
    headers.put("flatform", "android");
    NetworkConfig config = NetworkConfig.newBuilder()
            .setConnTimeout(10 * 1000)
            .setReadTimeout(10 * 1000)
            .setWriteTimeout(10 * 1000)
            .setCookieDomain("yourdomain.com")
            .setDeleteCookieKey("deleted")
            .setWorkerNumber(8)
            .setDebug(true)
            .setDiskCachePath("networklibcache")
            .setDiskCacheSize(1024 * 1024)
            .setMustSpecifiedRequest(false)
            .setLogTag("NetworkManager")
            .setHeader(headers)
            .setForceIgnoreCookieDomainCheck(true)
            .build();
    NetworkManager.getInstance().init(this, config);
}

然后分别请求form表格数据格式的请求和json数据格式的请求和GET请求

private void testJsonParamRequest() {
    String url = "http://www.yourdomain.com/jmconnection/connection.php";
    JSONObject obj = new JSONObject();
    try {
        obj.put("ab", "11%3Ahide%7C701%3Ashow%7C801%3Ashow%7C901%3Ashow");
        obj.put("antifraud_sign", "58420247a79d7937aa92c936b9bf1200");
        obj.put("antifraud_tid", "1134814405");
    } catch (JSONException ex) {
        ex.printStackTrace();
    }
    BaseCustomJsonRequest request = new CustomJsonObjectRequest(Request.Method.POST, url, obj.toString(),
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    setText(response.toString());
                    Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_SHORT).show();
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
                }
            }
    );
    NetworkManager.getInstance().add(request);
}

private void testFormParamRequest() {
    int method = Request.Method.POST;
    String url = "https://www.yourdomain.com/v1/common/dynamic";
    HashMap<String, String> obj = new HashMap<>();
    obj.put("platform", "android");
    obj.put("source", "p-baidu-ppzq-bt");
    obj.put("site", "bj");

    CustomJsonObjectRequest hr = new CustomJsonObjectRequest(method, url, obj, new Response
            .Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            setText(response.toString());
            Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_SHORT).show();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
        }
    });
    NetworkManager.getInstance().add(hr);
}

private void testGetRequest() {
    int method = Request.Method.GET;
    String url = "https://suggest.taobao.com/sug?code=utf-8&q=车载";
    HashMap<String, String> obj = new HashMap<>();

    CustomJsonObjectRequest hr = new CustomJsonObjectRequest(method, url, obj, new Response
            .Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            setText(response.toString());
            Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_SHORT).show();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
        }
    });
    NetworkManager.getInstance().add(hr);
}
    原文作者:HyperionChen
    原文地址: https://www.jianshu.com/p/25ca354aadd8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞