Android working with Volley
Volley是google官方推出的一个开源网络访问库,在项目中直接使用它,而不需要写一大堆的重复的代码;
项目主页:
https://android.googlesource.com/platform/frameworks/volley
Volley中一个重要的类就是RequestQueue,不用多说,只看命名就知道它是一个请求队列,用于存放我们添加进去的网络请求;
我们可以通过Volley.newRequestQueue(Context context);获取一个RequestQueue对象,通常一个应用程序中使用一个RequestQueue实例即可,因此可以把RequestQueue实例存放在Application中,当做一个全局变量;
下面直接通过例子来学习此开源库的使用;
一、字符串请求
protected void stringRequest() {
String url = "http://www.baidu.com";
StringRequest sr = new StringRequest(Method.GET, url,
new Listener<String>() {
@Override
public void onResponse(String response) {
Log.e(tag, "" + response);
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
sr.setTag("tag");
reqQueue.add(sr);
}
其中reqQueue即为RequestQueue实例对象(同下文);
我们只需要产生一个StringRequest实例,然后添加进RequestQueue队列当中即可,在创建实例的时候,会分别设置请求成功和请求失败时的监听回调,在监听器里面我们可以做相应的处理;
二、Json请求
Json请求分别两种,分别是JsonObjectRequest和JsonArrayRequest,下边我们来看一个JsonObjectRequest请求;
protected void jsonObjectRequest() {
String url = "http://m.weather.com.cn/data/101010100.html";
JsonObjectRequest jor = new JsonObjectRequest(Request.Method.GET, url,
null, new Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.e(tag, "" + response);
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
jor.setTag("tag");
reqQueue.add(jor);
}
和StringRequest相仿,不再表述,同理JsonArrayRequest也是一样;
三、图片请求
protected void imageRequest() {
iv = (ImageView) findViewById(R.id.iv);
String url = "http://img0.bdstatic.com/img/image/shouye/hjxnzz04.jpg";
ImageRequest ir = new ImageRequest(url, new Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
iv.setImageBitmap(response);
}
}, 0, 0, Config.RGB_565, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
iv.setImageResource(R.drawable.ic_launcher);
}
});
ir.setTag("tag");
reqQueue.add(ir);
// ImageRequest的构造函数接收六个参数
// url:图片的URL地址
// listener:图片请求成功的回调
// maxWidth:允许图片最大的宽度,指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩.
// maxHeight:允许图片最大的高度
// decodeConfig:图片的颜色属性
// errorListener:图片请求失败的回调
}
ImageRequest和StringRequest差不多,不过可以通过设置maxWidth和maxHeight对图片进行压缩;
在上面这个请求中,我们只把请求回来的图片直接设置给了ImageView,并没有做其它处理,是否有点不严谨,内存溢出了咋办?请看下面!
四、ImageLoader
protected void imageLoader() {
iv = (ImageView) findViewById(R.id.iv);
String url = "http://img0.bdstatic.com/img/image/shouye/hjxnzz04.jpg";
ImageLoader loader = new ImageLoader(reqQueue, new BitmapCache());
ImageListener listener = new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
}
};
// listener = ImageLoader.getImageListener(iv, R.drawable.ic_launcher,
// R.drawable.ic_launcher);
loader.get(url, listener, 0, 0);
// ImageLoader明显要比ImageRequest更加高效,它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求.
// 它的内部也是使用ImageRequest来实现的;
}
ImageLoader功能就要强大一些,它可以对图片进行缓存,其实它内部还是通过ImageRequest来实现的;通过ImageLoader.get(url,listener,maxWidth,maxHeight)自动获取图片;如果需要详细的监听图片的获取过程,则new一个ImageListener实例,如果不需要,则通过ImageLoader.getImageListener(int defaultResouceId,int errorResourceId);来设置默认的图片和请求失败时的图片;
在创建ImageLoader实例的时候,需要一个ImageCache对象,我在这里简单自定义了一个ImageCache对象用于缓存图片;
public class BitmapCache implements ImageCache {
public static int getDefaultLruCacheSize() {
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
return cacheSize;
}
private final String tag = "BitmapCache";
private LruCache<String, Bitmap> mCache;
public BitmapCache() {
int maxSize = getDefaultLruCacheSize();
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) {
Log.e(tag, "getBitmap");
return mCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
Log.e(tag, "putBitmap");
mCache.put(url, bitmap);
}
}
五、NetworkImageView
protected void networkImageView() {
String url = "http://img0.bdstatic.com/img/image/shouye/hjxnzz04.jpg";
NetworkImageView niv = ...;
niv.setErrorImageResId(R.drawable.ic_launcher);
niv.setDefaultImageResId(R.drawable.ic_launcher);
ImageLoader loader = new ImageLoader(reqQueue, new BitmapCache());
niv.setImageUrl(url, loader);
// NetworkImageView是一个自定义控制,它是继承自ImageView的,在原生的基础之上加入了加载网络图片的功能
// 使用ImageRequest和ImageLoader这两种方式来加载网络图片,都可以传入一个最大宽度和高度的参数来对图片进行压缩,
// 但NetworkImageView并不需要提供任何设置最大宽高的方法也能够对加载的图片进行压缩.
// 这是由于NetworkImageView是一个控件,在加载图片的时候它会自动获取自身的宽高,然后对比网络图片的宽度,再决定是否需要对图片进行压缩.
// 也就是说,压缩过程是在内部完全自动化的,并不需要我们关心,NetworkImageView会始终呈现给我们一张大小刚刚好的网络图片.
}
NetworkImageView继承处ImageView,它的使用更加简单,它的一些特性上面已经列出,使用的时候直接把原始的ImageView替换即可;
六、补充
上面讲了几个常用的类的使用,下面对一些设置进行补充记录一下;
上面的网络请求都是最基本的请求,并没有带特定的参数,那么问题来了,如果我需要设定一些请求参数怎么办?请看下面!
Request在发出请求的时候,会调用两个方法getParams和getHeaders,分别读取请求时附带的参数和请求头,我们重写这两方法,把需要设置的参数给写进去即可,下面是一个简单的例子;
StringRequest sr = new StringRequest(Method.GET, url,
new Listener<String>() {
@Override
public void onResponse(String response) {
Log.e(tag, "" + response);
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("param1", "value1");
map.put("param2", "value2");
return map;
} @Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("Content-Type", "application/json");
return map;
}
};
七、管理缓存
<1>.RequestQueue默认会把数据缓存到本地,比如一张图片,一些相关方法参考DiskBasedCache类;但有时我们不需要对数据进行缓存,只需要在添加请求的时候通过Request.setShouldCache(false)即可;
<2>.查看缓存:
RequestQueue reqQueue = ...;
Cache cache = reqQueue.getCache();
Entry entry = cache.get(url);
if(entry != null){
try {
String data = new String(entry.data, "UTF-8");
// handle data, like converting it to xml, json, bitmap etc.,
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}else{
// Cached response doesn't exists. Make network call here
}
Cache还提供了其它相关的方法,比如remove{删除},invalidate{不会删除缓存的数据,而是使其失效,当网络请求成功获取到新数据时,会覆盖掉之前的数据},clear{清空};
除了使用Cache.clear()方法清空缓存,还有另外一种方法来请空缓存:
protected void clearCache() {
ClearCacheRequest ccr = new ClearCacheRequest(reqQueue.getCache(),
new Runnable() {
@Override
public void run() {
}
});
ccr.setTag(this);
reqQueue.add(ccr);
}
八、取消请求
有时候,我们可能需要手动取消请求,比如,在一个请求还未完成时,程序即出了,如果再继续请求没有太大的意义,还有可能造成程序崩溃,通常这种情况我们在onStop方法中取消请求,下面就来看看如何取消请求;
RequestQueue reqQueue ...;
reqQueue.cancelAll(this);
// reqQueue.cancelAll(new RequestFilter() {
// @Override
// public boolean apply(Request<?> request) {
// return false;
// }
// });
九、自定义Request
先来看StringRequest的源码实现
public class StringRequest extends Request<String> {
private final Listener<String> mListener;
/**
* Creates a new request with the given method.
*
* @param method the request {@link Method} to use
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
public StringRequest(int method, String url, Listener<String> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
/**
* Creates a new GET request.
*
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
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));
}
}
通过上面StringRequest的源码,相信实现一个自定义Request对大家来说都没有太大的难度,也就是重写两个方法,deliverResponse(仅仅一行代码,有什么难的?)和parseNetworkResponse,主要就是实现parseNetworkResponse,下面参照StringRequest来实现一个XmlRequest;
public class XmlRequest extends Request<XmlPullParser> {
private Listener<XmlPullParser> listener;
public XmlRequest(int method, String url, Listener<XmlPullParser> listener,
ErrorListener errorlistener) {
super(method, url, errorlistener);
this.listener = listener;
}
public XmlRequest(String url, Listener<XmlPullParser> listener,
ErrorListener errorlistener) {
this(Method.GET, url, listener, errorlistener);
}
@Override
protected Response<XmlPullParser> parseNetworkResponse(
NetworkResponse response) {
try {
String str = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(new StringReader(str));
return Response.success(parser,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError());
}
}
@Override
protected void deliverResponse(XmlPullParser response) {
listener.onResponse(response);
}
}
十、自定义Request2(GsonRequest)
对于上面的JsonObjectRequest,我们只是得到了JSONObject,联想Gson,我们是否也可以直接把获取到的Json数据转换为一个实体对象呢?当然可以,而且也非常简单;
public class GsonRequest<T> extends Request<T> {
private Listener<T> listener;
private Gson gson;
private Class<T> clazz;
public GsonRequest(int method, String url, Class<T> clazz,
Listener<T> listener, ErrorListener errorlistener) {
super(method, url, errorlistener);
this.listener = listener;
this.clazz = clazz;
gson = new Gson();
}
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 str = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(gson.fromJson(str, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
}
完!
参考:http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
Android working with Volley的更多相关文章
- Android网络框架Volley(体验篇)
Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...
- Android网络框架Volley(实战篇)
之前讲了ym—— Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看如何把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQu ...
- Android网络框架-Volley实践 使用Volley打造自己定义ListView
这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影 ...
- Android网络框架Volley
Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...
- ym—— Android网络框架Volley(终极篇)
转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看Android网络框架Volley(体验篇)和 ...
- ym—— Android网络框架Volley(体验篇)
VolleyGoogle I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...
- Android开源框架——Volley
Volley 是 Google 在 2013 I/O 大会上推出的 Android 异步网络请求框架和图片加载框架.特别适合数据量小,通信频繁的网络操作.Volley 主要是通过两种 Diapatch ...
- Android中关于Volley的使用(五)从RequestQueue开始来深入认识Volley
在前面的几篇文章中,我们学习了如何用Volley去网络加载JSON数据,如何利用ImageRequest和NetworkImageView去网络加载数据,而关于Volley的使用,我们都是从下面一行代 ...
- Android 网络通信框架Volley简介
1.1. Volley引入的背景在以前,我们可能面临如下很多麻烦的问题. 比如以前从网上下载图片的步骤可能是这样的流程: 在ListAdapter#getView()里开始图像的读取. 通过Async ...
- Android之使用Volley框架在ListView中加载大量图片
1.listview 中的条目要用 Volley 中的 NetworkImageView,如果直接用ImageView也可以,但是要在getView方法中使用url地址设置为imageView的tag ...
随机推荐
- [游戏模版15] Win32 飞机射击
>_<:Only give you the code,try to understand it! >_<:picture resource #include <windo ...
- Backbone Model——数据模型
Model是Backbone中所有数据模型的基类,用于封装原始数据,并提供对数据进行操作的方法,我们一般通过继承的方式来扩展和使用它. 如果你做过数据库开发,可能对ORM(对象关系映射)不会陌生,而B ...
- JavaScript this 总结(含 ES6)
本文主要总结自<JavaScript 语言精粹>.部分总结自<JavaScript 高级程序设计>以及自己的经验 四种调用模式 在 JavaScript 中,this 的值取决 ...
- xdebug影响php运行速度
我在本地wamp的环境下面加了xdebug用来调试,但是我发现wordpress运行速度好慢,所有程序运行变得也很慢.开始以为是数据库有问题,找了半天,发现把xdebug的扩展去掉,就正常了. 目前配 ...
- js运动:多div变宽、二级菜单
定时器及运动函数. 多div变宽: <!-- Author: XiaoWen Create a file: 2016-12-13 09:36:30 Last modified: 2016-12- ...
- javaweb回顾第一篇servlet的学习和理解
前言:关于servlet相信学过java的都不会陌生,我最近又把这些基础知识整理一遍,便于自已能更好的理解ssm或者ssh,下面开始 1:Servlet接口 servlet有5个方法下面分别简单的介绍 ...
- Less/Sass编译工具,koala使用指南
如果你正在使用sass.less或coffee,而没有注意到koala, 那说明你可能已经好久没有更新你的知识库了.koala这个由国人编写的,用于编译sass.less.coffee利器,在最近的短 ...
- Scala access modifiers and qualifiers in detail
来自:http://www.jesperdj.com/2016/01/08/scala-access-modifiers-and-qualifiers-in-detail/ Just like Jav ...
- SecureCRT的快捷键
快捷键,有时比笨拙的方式,要效率高很多,近期经常和Linux打交道,用到SecureCRT,这里就从网上找到部分快捷方式,作为日后查看,以防经常查找. Alt + Enter -- 全屏Alt + B ...
- Android Dagger依赖注入框架浅析
今天接触了Dagger这套android的依赖注入框架(DI框架).感觉跟Spring 的IOC差点儿相同吧.这个框架它的优点是它没有採用反射技术(Spring是用反射的),而是用预编译技术.因为基于 ...