Android中volley封装实践记录(二)

前言

关于android的volley封装之前写过一篇文章,见链接(https://www.jb51.net/article/155875.htm)。这篇文章主要是换种方式进行封装,具体步骤如下所示。

步骤如下

1.创建Request,并设置相应的参数:

public class CommonJsonObjectRequest extends JsonObjectRequest {

private String TAG = this.getClass().getSimpleName();

/*

* code=1:处理成功;

*/

public static final int CODE_SUCCESS = 100;

private Context mContext;

private JSONObject mJsonRequest;

public CommonJsonObjectRequest(Context context, int method, String url,

JSONObject jsonRequest, Response.Listener<JSONObject> listener,

Response.ErrorListener errorListener) {

super(method, url, jsonRequest, listener, errorListener);

init(context, jsonRequest);

}

/**

* @param context

* @param url

* @param jsonRequest

* @param listener

* @param errorListener

*/

public CommonJsonObjectRequest(Context context, String url, JSONObject jsonRequest,

Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {

super(url, jsonRequest, listener, errorListener);

if (jsonRequest != null) {

Log.d(TAG, jsonRequest.toString());

}

init(context, jsonRequest);

}

/**

* @param context

* @param jsonRequest

*/

private void init(Context context, JSONObject jsonRequest) {

this.mContext = context.getApplicationContext();

this.mJsonRequest = jsonRequest;

setRetryPolicy(new DefaultRetryPolicy(10 * 1000, 0, 0));

}

@Override

public Map<String, String> getHeaders() throws AuthFailureError {

Map<String, String> headersMap = new HashMap<>();

//do your business requirement

return headersMap;

}

}

所做的工作也很简单,去配置网络访问RetryPolicy,比如超时时间,最大的重试次数。例外也会根据业务要求在请求的头部加入token等标识。

2.通过工厂模式创建请求队列,volley内部会有两种构造方式,同步请求或者异步请求,通过设置ResponseDelivery 可以实现。

public interface ResponseDelivery {

/**

* Parses a response from the network or cache and delivers it.

*/

public void postResponse(Request<?> request, Response<?> response);

/**

* Parses a response from the network or cache and delivers it. The provided

* Runnable will be executed after delivery.

*/

public void postResponse(Request<?> request, Response<?> response, Runnable runnable);

/**

* Posts an error for the given request.

*/

public void postError(Request<?> request, VolleyError error);

}

这个工厂的代码如下:

/**

* 网络请求队列工厂类

*/

public class RequestQueueFactory {

private static RequestQueue sRequestQueue;

private static RequestQueue sAsynRequestQueue;

private static int ASYN_QUEUE_THREAD_POOL_SIZE = 3;

private RequestQueueFactory() {

}

/**

* 获取默认RequestQueue,回调是同步到主线程的

*

* @param context

* @return

*/

public synchronized static RequestQueue getRequestQueue(Context context) {

if (sRequestQueue == null) {

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

OkHttpStack stack = new OkHttpStack(okHttpClient);

sRequestQueue = Volley.newRequestQueue(context, stack);

}

return sRequestQueue;

}

/**

* 获取异步RequestQueue,回调是在异步线程的

*

* @param context

* @return

*/

public synchronized static RequestQueue getAsynRequeQueueRespond(

final Context context) {

if (sAsynRequestQueue == null) {

sAsynRequestQueue = getAsynRequeQueueRespond(context,

ASYN_QUEUE_THREAD_POOL_SIZE);

}

return sAsynRequestQueue;

}

private static RequestQueue getAsynRequeQueueRespond(final Context context,

int threadPoolSize) {

File cacheDir = new File(context.getCacheDir(), "volley_asyn");

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

OkHttpStack stack = new OkHttpStack(okHttpClient);

Network network = new BasicNetwork(stack);

RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir),

network, threadPoolSize, new ExecutorDelivery(

AsyncTask.SERIAL_EXECUTOR));

queue.start();

return queue;

}

}

在代码中有这样两行代码:

if (sRequestQueue == null) {

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

OkHttpStack stack = new OkHttpStack(okHttpClient);

sRequestQueue = Volley.newRequestQueue(context, stack);

}

这里是使用了okhttpstack,如果不进行设置,内部默认的会设置一个stack;

if (stack == null) {

if (Build.VERSION.SDK_INT >= 9) {

stack = new HurlStack();

} else {

// Prior to Gingerbread, HttpUrlConnection was unreliable.

// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html

stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));

}

}

okhttpstack类如下:

/**

* 使用OKHttp作为底层的HttpStack

*/

public class OkHttpStack implements HttpStack {

private final OkHttpClient client;

public OkHttpStack(OkHttpClient client) {

this.client = client;

}

private static HttpEntity entityFromOkHttpResponse(Response response) throws IOException {

BasicHttpEntity entity = new BasicHttpEntity();

ResponseBody body = response.body();

entity.setContent(body.byteStream());

entity.setContentLength(body.contentLength());

entity.setContentEncoding(response.header("Content-Encoding"));

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

entity.setContentType(body.contentType().type());

}

return entity;

}

@SuppressWarnings("deprecation")

private static void setConnectionParametersForRequest

(okhttp3.Request.Builder builder, Request<?> request)

throws IOException, AuthFailureError {

switch (request.getMethod()) {

case Request.Method.DEPRECATED_GET_OR_POST:

byte[] postBody = request.getPostBody();

if (postBody != null) {

builder.post(RequestBody.create

(MediaType.parse(request.getPostBodyContentType()), postBody));

}

break;

case Request.Method.GET:

builder.get();

break;

case Request.Method.DELETE:

builder.delete();

break;

case Request.Method.POST:

builder.post(createRequestBody(request));

break;

case Request.Method.PUT:

builder.put(createRequestBody(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(createRequestBody(request));

break;

default:

throw new IllegalStateException("Unknown method type.");

}

}

private static RequestBody createRequestBody(Request request) throws AuthFailureError {

final byte[] body = request.getBody();

if (body == null) return null;

return RequestBody.create(MediaType.parse(request.getBodyContentType()), body);

}

private static 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");

}

@Override

public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)

throws IOException, AuthFailureError {

int timeoutMs = request.getTimeoutMs();

OkHttpClient client = this.client.newBuilder()

.readTimeout(timeoutMs, TimeUnit.MILLISECONDS)

.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS)

.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS)

.build();

okhttp3.Request.Builder okHttpRequestBuilder = new okhttp3.Request.Builder();

Map<String, String> headers = request.getHeaders();

for (Map.Entry<String,String> entry : headers.entrySet()) {

okHttpRequestBuilder.addHeader(entry.getKey(), entry.getValue());

}

for (Map.Entry<String,String> entry : additionalHeaders.entrySet()) {

okHttpRequestBuilder.addHeader(entry.getKey(), entry.getValue());

}

// for (final String name : headers.keySet()) { //entrySet的遍历效率比keySet高上一个遍历元素的速度

// okHttpRequestBuilder.addHeader(name, headers.get(name));

// }

// for (final String name : additionalHeaders.keySet()) {

// okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));

// }

setConnectionParametersForRequest(okHttpRequestBuilder, request);

okhttp3.Request okhttp3Request = okHttpRequestBuilder.url(request.getUrl()).build();

Response okHttpResponse = client.newCall(okhttp3Request).execute();

StatusLine responseStatus = new BasicStatusLine

(

parseProtocol(okHttpResponse.protocol()),

okHttpResponse.code(),

okHttpResponse.message()

);

BasicHttpResponse response = new BasicHttpResponse(responseStatus);

response.setEntity(entityFromOkHttpResponse(okHttpResponse));

Headers responseHeaders = okHttpResponse.headers();

for (int i = 0, len = responseHeaders.size(); i < len; i++) {

final String name = responseHeaders.name(i), value = responseHeaders.value(i);

if (name != null) {

response.addHeader(new BasicHeader(name, value));

}

}

return response;

}

}

其中核心代码在performRequest方法中。

3.封装基类。基类使用abstract会更灵活,子类可以选择性的重写方法。

/**

* 网络处理基类

*/

public abstract class BaseNetModel {

protected RequestQueue requestQueue;

protected Context context;

protected Object mTag;

protected BaseNetModel(Context context) {

this.context = context.getApplicationContext();

requestQueue = RequestQueueFactory.getAsynRequeQueueRespond(this.context);

}

protected BaseNetModel(Context context, boolean isAsyn) {

this.context = context.getApplicationContext();

requestQueue = isAsyn ? RequestQueueFactory.getAsynRequeQueueRespond(this.context)

: RequestQueueFactory.getRequestQueue(context);

}

/**

* 推荐用页面ClassName+时间戳

*

* @param tag

*/

public void setTag(Object tag) {

this.mTag = tag;

}

public void destroy() {

if (mTag != null) {

cancelTaskByTag(mTag);

}

requestQueue = null;

context = null;

}

public void cancelTaskByTag(Object tag) {

if (requestQueue != null) {

requestQueue.cancelAll(tag);

}

}

public void addRequest(String path, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {

addRequest(path, true, jsonRequest, listener, errorListener);

}

/**

* @param path 不带域名的接口路径

* @param withTag 是否带上页面的tag

* @param jsonRequest

* @param listener

* @param errorListener

*/

public void addRequest(String path, boolean withTag, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {

addRequestUrl(path, withTag, jsonRequest, listener, errorListener);

}

/**

* @param url 完整接口地址

* @param withTag

* @param jsonRequest

* @param listener

* @param errorListener

*/

public void addRequestUrl(String url, boolean withTag, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {

if (jsonRequest == null) {

jsonRequest = new JSONObject();

}

CommonJsonObjectRequest request = new CommonJsonObjectRequest(context, url, jsonRequest, listener, errorListener);

if (withTag && mTag != null) {

request.setTag(mTag);

}

requestQueue.add(request);

}

}

4.逻辑封装。

这里选用的是一个新闻的接口,这种接口可以在聚合数据上申请,有的收费,有的免费。

public class NewsModel extends BaseNetModel {

public NewsModel(Context context) {

super(context);

}

public NewsModel(Context context, boolean isAsyn) {

super(context, isAsyn);

}

public void getInfo(Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) throws Exception {

JSONObject jsonObject = new JSONObject();

addRequest(INetConstant.NEWS, jsonObject, listener, errorListener);

}

}

接口的地址为:(http://v.juhe.cn/toutiao/index?type=&key=b2f8e4aeacfa310cabfadd5189bbe4d5)

5.开始使用。

NewsModel newsModel = new NewsModel(getActivity());

try {

newsModel.getInfo(new Response.Listener<JSONObject>() {

@Override

public void onResponse(final JSONObject response) {

ThreadUtils.runInUIThread(new Runnable() {

@Override

public void run() {

News news = new Gson().fromJson(response.toString(), News.class);

mAdapter.setData(news.getResult().getData());

}

});

}

}, new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

}

});

} catch (Exception e) {

e.printStackTrace();

}

最后放一张图:

图片发自简书App

分享结束,代码在[github] (https://github.com/daydaydate/sample (本地下载))  。感谢您的阅读。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

以上是 Android中volley封装实践记录(二) 的全部内容, 来源链接: utcz.com/p/241619.html

回到顶部