您好,欢迎访问一九零五行业门户网

Android开发—Volley具体的使用详解

0. 前言  
android系统中主要提供了httpurlconnection和httpclient进行网络通信,但是如果不对其进行封装就很容易就会写出重复代码。因此一些android网络通信框架应运而生, volley就是其中的佼佼者,volley不仅可以进行http通信,也可以轻松加载网络上的图片。volley设计的初衷就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,volley的表现就会非常糟糕。原因总结如下:
(1)volley的网络请求线程池默认为4。因此只能并发进行4个请求(多了排队),容易被4个较大文件的下载任务阻塞其余请求。
(2)request的parsenetworkresponse()方法返回byte[]类型,需要把传输到的数据读到内存中。如果文件过大,容易引发oom。
1.  volley的基本使用
1.1  http get请求
首先在as中导入volley的jar包。
requestqueue mqueue = volley.newrequestqueue(getapplicationcontext()); stringrequest stringrequest_get = new stringrequest("http://www.baidu.com", new response.listener<string>() { @override public void onresponse(string response) { log.d("tag", response); } }, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { log.e("tag", error.getmessage(), error); } }); mqueue.add(stringrequest);
stringrequest的构造函数需要传入三个参数,第一个是url地址,第二/三个参数是服务器响应成功/失败的回调。若成功则将返回的html代码转为string打印出log。
1.2 http post请求
requestqueue mqueue = volley.newrequestqueue(getapplicationcontext()); stringrequest stringrequest = new stringrequest(method.post, url, listener, errorlistener) { @override protected map<string, string> getparams() throws authfailureerror { map<string, string> map = new hashmap<string, string>(); map.put("params1", "value1"); map.put("params2", "value2"); return map; } }; mqueue.add(stringrequest);
当发出post请求的时候,volley会尝试调用stringrequest的父类中的getparams()方法来获取post参数,因此我们需要在stringrequest中重写getparams()方法,设置post参数即可。
1.3 jsonrequest
和stringrequest一样,jsonrequest也是继承自request类的, jsonrequest是一个抽象类,有两个子类jsonobjectrequest和jsonarrayrequest,前者用于请求一段json数据的,后者用于请求一段json数组。下面是使用前者进行一段json请求的范例代码。
//队列初始化以及request加入队列略 jsonobjectrequest jsonobjectrequest = new jsonobjectrequest(url, null, new response.listener<jsonobject>() { @override public void onresponse(jsonobject response) { log.d("tag", response.tostring()); } }, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { log.e("tag", error.getmessage(), error); } });
1.4 imagerequest
volley支持对图片的加载,因为imagerequest也是继承自request类,因此用法也大同小异。下面直接传入图片url,返回数据后内部解析为bitmap,最后设置给imageview。否则设置默认图片。
imagerequest imagerequest = new imagerequest(url_image, new response.listener<bitmap>() { @override public void onresponse(bitmap response) { imageview.setimagebitmap(response); } }, 0, 0, config.rgb_565, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { imageview.setimageresource(r.drawable.default_image); } });
需要注意的是,第三/四个参数用于指定允许图片最大的宽/高,若网络图片的实际宽高大于该设定值,则会对图片进行压缩,指定成0的话就表示不进行压缩。第五个参数用于指定图片的颜色属性,bitmap.config下的几个常量都可以在这里使用,其中argb_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而rgb_565则表示每个图片像素占据2个字节大小。不过这种加载图片的方式并不被推荐,因为下面有更好的。
1.5 imageloader
imageloader基于imagerequest实现,并且更加智能,多出了帮图片缓存的功能,还可以过滤掉重复的请求链接。但是imageloader已经不再继承自request类。
//mqueue初始化略 imageloader imageloader = new imageloader(mqueue, new bitmapcache()); imagelistener listener = imageloader.getimagelistener(imageview, r.drawable.default_image, r.drawable.failed_image); imageloader.get(url_image, listener, 200, 200); //限制最大宽高 public class bitmapcache implements imagecache { //内部使用lru实现 private lrucache<string, bitmap> mcache; public bitmapcache() { //缓存图片的大小设置为10m int maxsize = 10 * 1024 * 1024; mcache = new lrucache<string, bitmap>(maxsize) { @override protected int sizeof(string key, bitmap bitmap) { return bitmap.getrowbytes() * bitmap.getheight(); } }; } @override public bitmap getbitmap(string url) { return mcache.get(url); } @override public void putbitmap(string url, bitmap bitmap) { mcache.put(url, bitmap); } }
第二行构造一个imageloader对象,其中第二个参数是一个imagecache对象,参数二为自定义的用户缓存的类bitmapcache,该类继承了imagecache。第三行获取一个imagelistener对象,传入参数比较简单,看名字就知道了。第四行调用imageloader的get()方法来加载图片。
1.6 networkimageview
这是第三种加载图片的方式,相对来说也是被用的比较多的方式。networkimageview继承自imageview的,在原生的基础之上加入了加载网络图片的功能。用法仍旧是先创建一个requestqueue对象和一个imageloader对象。接下来是在xml中定义我们的networkimageview,宽高表示裁剪到此宽高,wrap_content表示不裁剪。
<com.android.volley.toolbox.networkimageview android:id="@+id/network_image_view" android:layout_width="100dp" android:layout_height="100dp"/>
在activity中获取到networkimageview实例后,就可以调用它的setdefaultimageresid()方法、seterrorimageresid()方法和setimageurl()方法来分别设置加载时显示的图片,加载失败时显示的图片,以及目标图片的url地址。
networkimageview.setdefaultimageresid(r.drawable.default_image); networkimageview.seterrorimageresid(r.drawable.failed_image); networkimageview.setimageurl(url_image,imageloader);
2. 自定义request
在网络上传输的数据常用到xml和json格式,那么如果想要请求一条xml/json格式的数据就需要拓展我们的volley。
2. 1 xmlrequest
public class stringrequest extends request<string> { private final listener<string> mlistener; public stringrequest(int method, string url, listener<string> listener, errorlistener errorlistener) { super(method, url, errorlistener); mlistener = listener; } public stringrequest(string url, listener<string> listener, errorlistener errorlistener) { this(method.get, url, listener, errorlistener); } @override protected void deliverresponse(string response) { mlistener.onresponse(response); } @override protected response<string> parsenetworkresponse(networkresponse response) { string parsed; try { parsed = new string(response.data, httpheaderparser.parsecharset(response.headers)); } catch (unsupportedencodingexception e) { parsed = new string(response.data); } return response.success(parsed, httpheaderparser.parsecacheheaders(response)); } }
拓展之前先要看一下原有的request的子类是如何实现的,上面以stringrequest为例。stringrequest中提供了两个有参的构造函数,参数包括请求类型,请求地址,以及响应回调等,在构造函数中一定要调用super()方法将这几个参数传给父类,因为http的请求和响应都是在父类中处理的。
由于request类中的deliverresponse()和parsenetworkresponse()是两个抽象方法,因此stringrequest中对这两个方法进行了实现。前者调用了mlistener中的onresponse()方法,并将response内容传入即完成了将服务器响应的数据进行回调。后者对服务器响应的数据进行解析,其中数据是以字节的形式存放在networkresponse的data变量中(前言中在volley为什么不适合大文件下载就讲到了),这里将数据取出然后组装成一个string,并传入response的success()方法中。
在了解了stringrequest之后,我们自定义实现我们的xmlrequest。
public class xmlrequest extends request<xmlpullparser> { private final listener<xmlpullparser> mlistener; public xmlrequest(int method, string url, listener<xmlpullparser> listener, errorlistener errorlistener) { super(method, url, errorlistener); mlistener = listener; } public xmlrequest(string url, listener<xmlpullparser> listener, errorlistener errorlistener) { this(method.get, url, listener, errorlistener); } @override protected void deliverresponse(xmlpullparser response) { mlistener.onresponse(response); } @override protected response<xmlpullparser> parsenetworkresponse(networkresponse response) { try { //先转为字符串 string xmlstring = new string(response.data, httpheaderparser.parsecharset(response.headers)); //重点在于解析xml xmlpullparserfactory factory = xmlpullparserfactory.newinstance(); xmlpullparser xmlpullparser = factory.newpullparser(); xmlpullparser.setinput(new stringreader(xmlstring)); //返回xmlpullparser实例 return response.success(xmlpullparser, httpheaderparser.parsecacheheaders(response)); } catch (unsupportedencodingexception e) { return response.error(new parseerror(e)); } catch (xmlpullparserexception e) { return response.error(new parseerror(e)); } } } //使用我们的xmlrequest xmlrequest xmlrequest = new xmlrequest( url_xml, new response.listener<xmlpullparser>() { @override public void onresponse(xmlpullparser response) { try { int eventtype = response.geteventtype(); while (eventtype != xmlpullparser.end_document) { switch (eventtype) { case xmlpullparser.start_tag: string nodename = response.getname(); if (wanted_tag.equals(nodename)) { string pname = response.getattributevalue(0); log.d("tag", "pname is " + pname); } break; } eventtype = response.next(); } } catch (xmlpullparserexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } } }, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { log.e("tag", error.getmessage(), error); } });
2. 2 gsonrequest
用过gson的都知道gson解析有多方便,这里可以把volley和gson结合在一起吗?当然可以。重写代码基本上大同小异。前提是先导入gson的jar包。
public class gsonrequest<t> extends request<t> { private final listener<t> mlistener; private gson mgson; private class<t> mclass; public gsonrequest(int method, string url, class<t> clazz, listener<t> listener, errorlistener errorlistener) { super(method, url, errorlistener); mgson = new gson(); mclass = clazz; mlistener = listener; } public gsonrequest(string url, class<t> clazz, listener<t> listener, errorlistener errorlistener) { this(method.get, url, clazz, listener, errorlistener); } @override protected response<t> parsenetworkresponse(networkresponse response) { try { string jsonstring = new string(response.data, httpheaderparser.parsecharset(response.headers)); //结合gson解析 return response.success(mgson.fromjson(jsonstring, mclass), httpheaderparser.parsecacheheaders(response)); } catch (unsupportedencodingexception e) { return response.error(new parseerror(e)); } } @override protected void deliverresponse(t response) { mlistener.onresponse(response); } } //使用我们的gsonrequest gsonrequest<weather> gsonrequest = new gsonrequest<weather>(url_json,yourclass.class, new response.listener<weather>() { @override public void onresponse(yourclass obj) { //这里获得obj对应的json中的数据 } }, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { log.e("tag", error.getmessage(), error); } });
以上就是android开发—volley具体的使用详解的详细内容。
其它类似信息

推荐信息