Android--Volley基本用法及自定义
最近在看网络通信这块时,频繁的使用到Http通信,而Android系统中主要提供两种方式来进行Http通信,HttpURLConnection和HttpClient。不过在实际使用在还是有点麻烦和复杂的。经常一不小心就出错,在群里看到有人推荐使用Valley,对齐进行了很好的封装,简单方便。
Volley是2013 GoogleI/O大会上推出的网络通信框架,所以在性能方面是毋庸置疑的。下面算是总结一下自己对于Volley的学习笔记吧。
下载Volley
如果你的电脑上装有Git,可以使用如下命令下载Volley的源码:
1 git clone https://android.googlesource.com/platform/frameworks/volley
这里放出部分功能看看:
准备工作做好以后就开始正式用了,我这里只以Http通信来介绍,其他的也需要进一步去了解了。
1.StringRequest
1.首先的获取到一个RequestQueue对象
1 RequestQueue mQueue= Volley.newRequestQueue(context);
2.发送一条Http请求,我们需要创建一个StringRequest对象:
1 StringRequest stringRequest=new StringRequest("http://www.baidu.com", new Response.Listener<String>() { 2 @Override 3 public void onResponse(String s) { 4 Log.d(TAG, "onResponse: "+s); 5 } 6 }, new Response.ErrorListener() { 7 @Override 8 public void onErrorResponse(VolleyError volleyError) { 9 Log.e(TAG,volleyError.getMessage(),volleyError); 10 } 11 });
这里StringRequest里面需要传入三个参数:第一个参数是目标url地址,第二个是服务器响应成功的的回调,第三个是服务器响应失败的回调。我这里就用log代替具体回调内容。
3.将这个stringRequest添加到RequestQueue里面:
1 mQueue.add(stringRequest);
打开LogCat就会看到下面这样:
至于内容我就先不去管那么多了。能够得到结果就证明没错了。前面用到的只是Get请求,如果你想使用Post则需要添加参数来指定请求类型,如下:
1 StringRequest stringRequest=new StringRequest(Request.Method.POST,"http://www.baidu.com",listener,erroelistener)
这里还只是指定了请求类型如果需要提交给服务器还是不行的,还需要重写getParams()方法,如下:
简单来说,就是三步操作:
1.创建一个RequestQueue对象。
2.创建一个StringRequest对象。
3.将StringRequest对象添加到RequestQueue里面。
因为Volley是开源,如果不满足现在的使用,你大可以自己添加或者修改自己想要的方法。同样的JsonRequest和JsonObjectRequest还有ImageRequest用法是相同的,想了解的可以自己实践。
2.ImageLoader
1. 创建一个RequestQueue对象:
1 RequestQueue mQueue= Volley.newRequestQueue(context);
2.创建一个ImageLoader对象:
1 ImageLoader imageLoader=new ImageLoader(mQueue,bitmapCache);
这里第一个参数为一个RequestQueue对象,第二个参数为ImageCache对象。下面会贴出bitmapCache代码
3.调用ImageLoader的get()方法加载图片:
1 imageLoader.get("http://images.cnblogs.com/cnblogs_com/yeshuwei/837768/o_u=733417015,367501698_fm=11_gp=0.jpg",listener);
这里第一个参数为图片的Url地址,第二个参数为一个ImageListener对象,可以通过如下获取:
ImageLoader.ImageListener listener=imageLoader.getImageListener(imageView,R.mipmap.defaulting,R.mipmap.error);
第一个参数用于指定显示图片的ImageView空间,第二个图片为加载时显示的图片,第三个为加载错误时候显示的图片。
你也可以通过在get()方法中指定图片的高度和宽度:
1 imageLoader.get("http://images.cnblogs.com/cnblogs_com/yeshuwei/837768/o_u=733417015,367501698_fm=11_gp=0.jpg",
2 listener, 200, 200);
BitmapCache代码:
1 public class BitmapCache implements ImageLoader.ImageCache { 2 private LruCache<String, Bitmap> mCache; 3 4 public BitmapCache() { 5 int maxSize = 10 * 1024 * 1024; 6 mCache = new LruCache<String, Bitmap>(maxSize) { 7 @Override 8 protected int sizeOf(String key, Bitmap bitmap) { 9 return bitmap.getRowBytes() * bitmap.getHeight(); 10 } 11 }; 12 } 13 14 @Override 15 public Bitmap getBitmap(String url) { 16 return mCache.get(url); 17 } 18 19 @Override 20 public void putBitmap(String url, Bitmap bitmap) { 21 mCache.put(url, bitmap); 22 } 23 }
ImageLoader就学习到这里了。
3.NetworkImageView
NetworkImageview是一种自定义控件用来加载图片,使用方法如下:
1.创建一个RequestQueue对象
2.在布局文件中加载一个NetworkImageView控件
3.创建一个ImageLoader对象
4.在代码中获取NetworkImageView控件的实例
5.设置要加载的图片
1 bitmapCache=new BitmapCache(); 2 networkImageView= (NetworkImageView) findViewById(R.id.network_image_view); 3 RequestQueue mQueue= Volley.newRequestQueue(context); 4 ImageLoader imageLoader=new ImageLoader(mQueue,bitmapCache); 5 networkImageView.setDefaultImageResId(R.mipmap.defaulting);//加载中显示的图片 6 networkImageView.setErrorImageResId(R.mipmap.error);//加载错误时显示的图片 7 networkImageView.setImageUrl("http://images.cnblogs.com/cnblogs_com/yeshuwei/837768/o_u=733417015,367501698_fm=11_gp=0.jpg",imageLoader);
setImageUrl接收两个参数,第一个是图片的Url地址,第二个为ImageLoader对象。
关于图片加载的目前就学到ImageRequest,ImageLoader,NetworkImageView三种。接下来讲讲自定义的Volley
4.XMLRequest
这里根据郭神的博客跟着学习了一下如何自定义的使用Volley,这里来自顶一个XMLRequest来解析一条XML格式的数据。
打开StringRequest和JsonRequest的源码发现都是继承自Request的并且Request是能够制定泛型类的,这样就能很好的扩张我们想要的东西了。
然后提供了两个有参数的构造方法和两个要重写的抽象方法。这里贴一下源码:
1 public class StringRequest extends Request<String> { 2 private final Listener<String> mListener; 3 4 public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { 5 super(method, url, errorListener); 6 this.mListener = listener; 7 } 8 9 public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { 10 this(0, url, listener, errorListener); 11 } 12 13 protected void deliverResponse(String response) { 14 this.mListener.onResponse(response); 15 } 16 17 protected Response<String> parseNetworkResponse(NetworkResponse response) { 18 String parsed; 19 try { 20 parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 21 } catch (UnsupportedEncodingException var4) { 22 parsed = new String(response.data); 23 } 24 25 return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); 26 } 27 }
需要注意的是,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中自动处理的。deliverResponse()方法中的实现很简单,仅仅是调用了mListener中的onResponse()方法,并将response内容传入即可,这样就可以将服务器响应的数据进行回调了。parseNetworkResponse()方法中则应该对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponse的data变量中的,这里将数据取出然后组装成一个String,并传入Response的success()方法中即可。
详情参考郭神博客:http://blog.csdn.net/guolin_blog/article/details/17612763
下面动手来跟着郭神试试手。
1 public class XMLRequest extends Request<XmlPullParser> { 2 private final Response.Listener<XmlPullParser> mListener; 3 4 public XMLRequest(int method, String url,Response.Listener<XmlPullParser> listener, 5 Response.ErrorListener errorListener) { 6 super(method, url, errorListener); 7 this.mListener = listener; 8 } 9 public XMLRequest(String url, Response.Listener<XmlPullParser> listener, Response.ErrorListener errorListener) { 10 this(Method.GET, url, listener, errorListener); 11 } 12 13 14 /*parseNetworkResponse()方法中则应该对服务器响应的数据进行解析, 15 其中数据是以字节的形式存放在NetworkResponse的data变量中的, 16 这里将数据取出然后组装成一个String,并传入Response的success()方法中即可。*/ 17 @Override 18 protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) { 19 try { 20 String xmlString=new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 21 XmlPullParserFactory factory=XmlPullParserFactory.newInstance(); 22 XmlPullParser parser=factory.newPullParser(); 23 parser.setInput(new StringReader(xmlString)); 24 return Response.success(parser, HttpHeaderParser.parseCacheHeaders(response)); 25 } catch (UnsupportedEncodingException e) { 26 return Response.error(new ParseError(e)); 27 }catch (XmlPullParserException e) { 28 return Response.error(new ParseError(e)); 29 } 30 31 } 32 /*deliverResponse()方法中的实现很简单,仅仅是调用了mListener中的onResponse()方法, 33 并将response内容传入即可,这样就可以将服务器响应的数据进行回调了。*/ 34 @Override 35 protected void deliverResponse(XmlPullParser xmlPullParser) { 36 mListener.onResponse(xmlPullParser); 37 } 38 }
下面来尝试用这个XMLRequest来请求一段XML数据
1 public class xmlRequest extends AppCompatActivity { 2 private Context context; 3 private static final String TAG = "xmlRequest"; 4 @Override 5 protected void onCreate(@Nullable Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 context=getApplicationContext(); 8 RequestQueue mQueue= Volley.newRequestQueue(context); 9 XMLRequest xmlr=new XMLRequest("http://flash.weather.com.cn/wmaps/xml/china.xml", new Response.Listener<XmlPullParser>() { 10 @Override 11 public void onResponse(XmlPullParser xmlPullParser) { 12 try { 13 int eventType=xmlPullParser.getEventType(); 14 while (eventType!=XmlPullParser.END_DOCUMENT){ 15 switch (eventType){ 16 case XmlPullParser.START_TAG: 17 String nodename=xmlPullParser.getName(); 18 if ("city".equals(nodename)){ 19 String pName=xmlPullParser.getAttributeValue(0); 20 Log.d(TAG, "pName is " + pName); 21 } 22 break; 23 } 24 try { 25 eventType=xmlPullParser.next(); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } 29 } 30 } catch (XmlPullParserException e) { 31 e.printStackTrace(); 32 } 33 } 34 }, new Response.ErrorListener() { 35 @Override 36 public void onErrorResponse(VolleyError volleyError) { 37 Log.e(TAG, volleyError.getMessage(),volleyError ); 38 } 39 }); 40 mQueue.add(xmlr); 41 } 42 }
其中http://flash.weather.com.cn/wmaps/xml/china.xml是一个用来以XMl格式还回中国所以省份数据的接口。
目前所学就这么些了,参考资料如下:
1.慕课网视频:http://www.imooc.com/learn/468
2.郭神博客:http://blog.csdn.net/guolin_blog?viewmode=contents
3.菜鸟驿站小猪关于XML数据解析讲解:http://www.runoob.com/w3cnote/android-tutorial-xml.html
RequestQueue mQueue= Volley.newRequestQueue(context);