Android:封装网络请求库Volley结合Okhttp
1. 前言
在拷贝Github的源码到本地时,有一个技巧,能节约很多修改package和import的时间
- 在Github下载源码的zip包到本地,解压
- 将下载的源码的java目录下的文件夹全部拷贝到目标位置的java目录下
- 修复一些第三方依赖的问题
- 再将目标位置的java目录下的包名整体移动到希望的包下面
这样做的好处时,让编辑器自动完成包名和导包的替换,不用手动替换。
2. 为什么要volley结合okhttp
okhttp是非常优秀的网络请求库,网络传输层非常好用,支持http和https,被google官方接受,但只是单纯的网络操作工具,没有封装异步操作。而volley是google推出的,可以取消请求,有请求缓存功能,在高并发且数据量小的场景非常适合,但是在大数据量请求表现糟糕,并且不支持https。因此将这两种结合起来,采用volley的高并发调度和缓存功能,采用okhttp网络传输功能。
3. 结合volley和okhttp的步骤
volley把网络传输层通过HttpStack接口的方式暴露出来,因此可以实现这个接口来替换Volley默认的网络传输层的实现
整个网络请求的流程:
- 首先将volley的Request转换为okhttp的Request
- 调用okhttp的网络传输层,将okhttp的Request转换为okhttp的Response
- 将okhttp的Response转换为apache的Response
- 将apache的Response转换为volley的Response
整合volley和okhttp的步骤:
- 实现OkHttpHelper类,将okhttp的网络操作封装一下
- 实现OkHttpInterceptor类,用于输出请求和返回的日志
- 实现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上。
- 实现HeaderStorage类,将请求的header数据(包括cookie数据)缓存起来
- 实现CookieStorage类,将请求的header中的cookie数据和返回的cookie数据缓存起来,供下次请求使用
- 实现CustomDiskCache类,指定volley的硬盘缓存策略
- 实现SecurityUtil类,解决okhttp的https证书校验问题
- 实现BaseCustomJsonRequest类和其子类CustomJsonObjectRequest和CustomJsonArrayRequest类,内部兼容json类型的请求数据和form表单类型的请求数据。
- 实现CustomJsonBody类,继承了RequestBody类,封装json数据的string类型转换为okhttp接受的RequestBody类型。
- 实现NetworkConfig类,完成整个网络库所提供对外的所有配置,包括超时时间、连接池数量、域名设置等等
- 实现NetworkLogger类,完成网络库关键数据的打印功能
- 实现NetworkManager类,内部实现网络库的初始化,已经网络请求的添加。这个类是暴露给外部使用的
- 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);
}