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的更多相关文章

  1. Android网络框架Volley(体验篇)

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  2. Android网络框架Volley(实战篇)

      之前讲了ym—— Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看如何把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQu ...

  3. Android网络框架-Volley实践 使用Volley打造自己定义ListView

    这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影 ...

  4. Android网络框架Volley

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  5. ym—— Android网络框架Volley(终极篇)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看Android网络框架Volley(体验篇)和 ...

  6. ym—— Android网络框架Volley(体验篇)

    VolleyGoogle I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  7. Android开源框架——Volley

    Volley 是 Google 在 2013 I/O 大会上推出的 Android 异步网络请求框架和图片加载框架.特别适合数据量小,通信频繁的网络操作.Volley 主要是通过两种 Diapatch ...

  8. Android中关于Volley的使用(五)从RequestQueue开始来深入认识Volley

    在前面的几篇文章中,我们学习了如何用Volley去网络加载JSON数据,如何利用ImageRequest和NetworkImageView去网络加载数据,而关于Volley的使用,我们都是从下面一行代 ...

  9. Android 网络通信框架Volley简介

    1.1. Volley引入的背景在以前,我们可能面临如下很多麻烦的问题. 比如以前从网上下载图片的步骤可能是这样的流程: 在ListAdapter#getView()里开始图像的读取. 通过Async ...

  10. Android之使用Volley框架在ListView中加载大量图片

    1.listview 中的条目要用 Volley 中的 NetworkImageView,如果直接用ImageView也可以,但是要在getView方法中使用url地址设置为imageView的tag ...

随机推荐

  1. thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase

    本节主要介绍缓冲相关的传输类,缓存的作用就是为了提高读写的效率.Thrift在实现缓存传输的时候首先建立一个缓存的基类,然后需要实现缓存功能的类都可以直接从这个基类继承.下面就详细分析这个基类以及一个 ...

  2. sql 取首次投资的人

    --- 11月 ---首次投资笔数和投资金额 ) AS stNum,sum(amount) AS stAmount FROM ( ),createtime,) AS riqi,a.amount,a.u ...

  3. Linux Buffers和Cached的区别(转)

    在linux下使用free命令查看内存使用情况,有buffers和cached两项,以下是它们的区别: buffers是为块设备设计的缓冲.比如磁盘读写,把分散的写操作集中进行,减少磁盘I/O,从而提 ...

  4. ios之VFL的补充(二)

    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[languageI ...

  5. 制作6寸 kindle pdf

    设置word 纸张大小为 90mm*117mm 然后保存为 pdf 就好了.

  6. 配置CENTOS YUM更新源

    众所周知,Centos 有个很方便的软件安装工具  yum,但是默认安装完centos,系统里使用的是国外的centos更新源,这就造成了我们使用默认更新源安装或者更新软件时速度很慢的问题. 为了使用 ...

  7. mysql 修改root登录密码

    mysql -u root -p 然后回车,进入(等于用空密码进入) 2 use mysql; update user set password=password('123456') where us ...

  8. mysql中You can’t specify target table for update in FROM clause错误解决方法

    mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表( ...

  9. Backbone.js Wine Cellar 教程

    中文版: http://rd.189works.com/article-74541-1.html http://www.189works.com/article-74542-1.html http:/ ...

  10. css3动画特效:纯css3制作win8加载动画特效

    Windows 8     完整效果如上图:这个里面可能是css冲突,喜欢的可以自己去体征一下:   css特效代码: <style type="text/css"> ...