当前位置: 移动技术网 > IT编程>移动开发>Android > Android中volley封装实践记录(二)

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

2019年07月29日  | 移动技术网IT编程  | 我要评论

赵本山小品相亲高清,钟依澄,非主流闪图头像

前言

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

步骤如下

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] ( ())  。感谢您的阅读。

总结

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网