热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

这篇文章主要给大家介绍了关于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 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 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 getHeaders() throws AuthFailureError {
 Map 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<&#63;> request, Response<&#63;> response);

 /**
 * Parses a response from the network or cache and delivers it. The provided
 * Runnable will be executed after delivery.
 */
 public void postResponse(Request<&#63;> request, Response<&#63;> response, Runnable runnable);

 /**
 * Posts an error for the given request.
 */
 public void postError(Request<&#63;> 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<&#63;> 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<&#63;> request, Map 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 headers = request.getHeaders();

 for (Map.Entry entry : headers.entrySet()) {
  okHttpRequestBuilder.addHeader(entry.getKey(), entry.getValue());
 }

 for (Map.Entry 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 

其中核心代码在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 &#63; 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 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 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 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 listener, Response.ErrorListener errorListener) throws Exception {
 JSONObject jsOnObject= new JSONObject();
 addRequest(INetConstant.NEWS, jsonObject, listener, errorListener);
 }
}

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

5.开始使用。

 NewsModel newsModel = new NewsModel(getActivity());
 try {
  newsModel.getInfo(new Response.Listener() {
  @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 (本地下载))  。感谢您的阅读。

总结

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


推荐阅读
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文介绍了Svn和Maven的使用说明,包括版本控制和构建工具的功能和优势。同时提供了一个相关链接,链接中详细介绍了SvnMaven的使用方法和注意事项。通过学习和使用SvnMaven,开发人员可以更好地进行代码管理、软件开发和协作开发,提高项目管理的效率和质量。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
author-avatar
哥哥很霸道_277
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有