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 (本地下载))  。感谢您的阅读。

总结

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

(0)

相关推荐

  • Android中volley封装实践记录

    前言 在项目中一般使用使用volley方式如下,用起来给人一种很乱的感觉,于是一种盘它的想法油然而生. public void get() { String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=......"; StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<

  • Android中Volley框架下保持会话方法

    公司经理把我拉出来,死马当活马医,做一个安卓app,作为刚毕业几个月且只是培训了几个月的小白来说,这无疑是一个非常大的挑战,当然最大的挑战不是这个,最大的挑战时两个周做出来.这是最蛋疼的,说实话,对于有两三年的开发经验的人来说,两个周开发一个项目很简单,说不定还有很多时间用来干别的. 于是一上来就把自己给难住了,登陆还是很好做的,只要验证返回的信息就可以跳转,但是在接下来后面的数据接口连接的时候各种报错,整了两天,查了很多信息,还接受了公司老人的嘲讽和谩骂终于做出来了. 这个是基于session

  • Android 中Volley二次封装并实现网络请求缓存

    Android 中Volley二次封装并实现网络请求缓存 Android目前很多同学使用Volley请求网络数据,但是Volley没有对请求过得数据进行缓存,因此需要我们自己手动缓存. 一下就是我的一种思路,仅供参考 具体使用方法为: HashMap<String,String> params = new HashMap<>(); params.put("id", "1"); params.put("user", &quo

  • Android Volley框架全面解析

     Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,几乎在任何项目的代码中我们都能看到这两个类的身影,使用率非常高. 不过HttpURLConnection和HttpClient的用法还是稍微有些复杂的,如果不进行适当封装的话,很容易就会写出不少重复代码.于是乎,一些Android网络

  • Android的HTTP类库Volley入门学习教程

    1. 什么是Volley 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,几乎在任何项目的代码中我们都能看到这两个类的身影,使用率非常高. 不过HttpURLConnection和HttpClient的用法还是稍微有些复杂的,如果不进行适当封装的话,很容易就会写出不少重复代码.于是乎,一些Androi

  • Android 开发中Volley详解及实例

    Android 开发中Volley详解及实例 最近在做项目的时候,各种get和post.简直要疯了,我这种啥都不了解的,不知道咋办了,然后百度看了下,可以用volley进行网络请求与获取,下面就介绍下volley的用法. volley有三种方式:JsonObjectRequest,JsonArrayRequest,StringRequest.其实都是差不多了,举一反三就ok了,这里我就讲下JsonObjectRequest. 方法如下: JsonObjectRequest jsonObjectR

  • android 网络请求库volley方法详解

    使用volley进行网络请求:需先将volley包导入androidstudio中 File下的Project Structrue,点加号导包 volley网络请求步骤: 1. 创建请求队列       RequestQueue queue = Volley.newRequestQueue(this); 2.创建请求对象(3种) StringRequest request = new StringRequest("请求方法","请求的网络地址","成功的网

  • Android Volley框架使用方法详解

    本文主要从两个方面对Android Volley框架的使用方法进行讲解,具体内容如下 一.网络请求 1.get方式请求数据 // 1 创建一个请求队列 RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this); // 2 创建一个请求 String url = "http://api.m.mtime.cn/PageSubArea/TrailerList.api"; StringRequest stri

  • Android 网络请求框架Volley实例详解

    Android 网络请求框架Volley实例详解 首先上效果图 Logcat日志信息on Reponse Volley特别适合数据量不大但是通信频繁的场景,像文件上传下载不适合! 首先第一步 用到的RequetQueue RequestQueue.Java RequestQueue请求队列首先得先说一下,ReuqestQueue是如何对请求进行管理的...RequestQueue是对所有的请求进行保存...然后通过自身的start()方法开启一个CacheDispatcher线程用于缓存调度,开

  • Android Volley框架使用源码分享

    过去在Android上网络通信都是使用的Xutils 因为用它可以顺道处理了图片和网络这两个方面,后来发觉Xutils里面使用的是HttpClient  而Google在6.0的版本上已经把HttpClient废除了,所以开始寻找新的网络框架,okhttp也用过,但是它是在作用在UI线程,使用起来还需要用handler 所以就先用着Volley框架了.  这里我先分析下Volley框架的简单网络请求的源码. 使用Volley请求网络数据的简单过程: RequestQueue queue = Vo

随机推荐