Android中volley封装实践记录(二)
程序员文章站
2022-03-08 17:14:23
前言
关于android的volley封装之前写过一篇文章,见链接()。这篇文章主要是换种方式进行封装,具体步骤如下所示。
步骤如下
1.创建request,并设...
前言
关于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] ( ()) 。感谢您的阅读。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
下一篇: Android仿美团拖拽效果实例代码