所谓Volley,它是2013年Google I/O上发布的一款网络框架,基于Android平台,能使网络通信更快,更简单,更健全。

它的优点:(1)默认Android2.3及以上基于HttpURLConnection,2.3以下使用基于HttpClient;(2)符合Http 缓存语义 的缓存机制(提供了默认的磁盘和内存等缓存);(3)请求队列的优先级排序;(4)提供多样的取消机制;(5)提供简便的图片加载工具(其实图片的加载才是我们最为看重的功能);(6)一个优秀的框架。

不足之处也有:它只适合数据量小,通信频繁的网络操作,如果是数据量大的,像音频,视频等的传输,还是不要使用Volley的为好。

一、获得Volley

可以直接从google上git clone下来

git clone https://android.googlesource.com/platform/frameworks/volley

然后生成jar包,导入到自己的项目中使用。注意,这个库要求最低SDK版本为Froyo,即至少要设置android:minSdkVersion为8以上。

不过由于google的被墙,所以可能要翻墙出去。嫌麻烦的话也可以直接问我要jar包。

二、使用Volley

volley里面自带了很多的工具类,像StringRequest,JsonArrayRequest,JsonObjectRequest,ImageRequest这些都是我们平时经常使用的http请求,我们就可以直接把它们拿过来用。现在来一一说明这些类的用法吧。

在此之前,先说一下Volley中的requestQueue吧,所有的request申请出来后都是扔到这个队列里处理。

requestQueue = Volley.newRequestQueue(context.getApplicationContext());
...
requestQueue.add(request);

这样Volley就会帮你处理网络通信了。

(1)字符数据的处理

  1. StringRequest 网络请求返回字符串
    StringRequest的网络请求返回的是一个字符串。它有两个构造函数

    /**
    * 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);
    }

    第二个构造函数相比第一个少了个method的参数,所以它是默认使用get方法。第一个构造函数是可以让我们自己定义请求的方式,method的类型定义在Request类中

        /**
    * Supported request methods.
    */
    public interface Method {
    int DEPRECATED_GET_OR_POST = -1;
    int GET = 0;
    int POST = 1;
    int PUT = 2;
    int DELETE = 3;
    int HEAD = 4;
    int OPTIONS = 5;
    int TRACE = 6;
    int PATCH = 7;
    }

    默认是get,而除此以外我们使用最多的是post的请求方法。

    Get请求:

            StringRequest request = new StringRequest(
    "http://www.baidu.com/",
    new Response.Listener<String>() {
    @Override
    public void onResponse(String arg0) { //收到成功应答后会触发这里 }
    },
    new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError volleyError) { //出现连接错误会触发这里

    }
    }
    );

    在StringRequest中传入一个url,一个通信成功的触发器和一个通信失败的触发器。
    而post的请求方式如下:

               StringRequest request = new StringRequest(
    Request.Method.POST,
    "http://xxx.xxx.xxx",
    new Response.Listener<String>() {
    @Override
    public void onResponse(String s) { }
    },
    new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError volleyError) { }
    }
    ) {
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError { //设置头信息
    Map<String, String> map = new HashMap<String, String>();
    map.put("Content-Type", "application/x-www-form-urldecoded");
    return map;
    } @Override
    protected Map<String, String> getParams() throws AuthFailureError { //设置参数
    Map<String, String> map = new HashMap<String, String>();
    map.put("name", "cpacm");
    map.put("password", "12345");
    return map;
    }
    };

    可以通过复写里面的方法把数据给传进去,不止如此,如果还想对返回的数据进行进一步的处理,可以在重写下面这个方法

                /**
    * 可以对返回的reponse做处理, NetworkResponse里面包括状态码,头信息,内容数据,是否缓存在本地,花费的时间(ms)等内容
    **/
    @Override
    protected Response<String> parseNetworkResponse(
    NetworkResponse response) {
    // 比如下面的例子是取头信息里的cookie数据
    /*
    * String mCookie;
    * for (String s : response.headers.keySet()) {
    * if (s.contains("Set-Cookie")) { mCookie =
    * response.headers.get(s); break; } }
    */
    return super.parseNetworkResponse(response);
    }

    与前面两个重写方法在通信前调用不同,这个方法是在通信结束后调用的。
    StringRequest的内容就那么多,不是很理解的话可以参考示例来仔细琢磨...

  2.  JsonObjectRequest json格式的数据通信
    JsonArrayRequest是专对于jsonArray的处理,而JsonObjectRequest是对jsonObject的处理,所以两个区别不大,所以我这里就主要介绍JsonObjectRequest的使用。
    事实上,使用的方法和StringRequest并没有什么大的区别,举一反三嘛。

    JsonObjectRequest的构造函数也是有两个,不过内容与StringRequest有一点不同。

    public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener)  
    
    public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) 

    第一个构造函数的参数分别为 请求方法,url地址,附带的jsonObject数据,成功监听器,失败监听器。

    第二个构造函数比第一个少了method的参数,它默认的规则是:当jsonRequest为空时,使用get请求方式,不为空则是使用post方式。

    由于构造函数中已经有了数据传递的参数,所以不必在重写getParams()的方法了(重写了也没用)。
    基本的调用方法:

    JsonObjectRequest request = new JsonObjectRequest(
    "http://xxx.xxx.xx",
    jsonObject,
    new Response.Listener<JSONObject>() {
    @Override
    public void onResponse(JSONObject jsonObject) { }
    },
    new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError volleyError) { }
    }
    ) {
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> map = new HashMap<String, String>();
    map.put("Cookie", mCookie);
    return map;
    }
    };

    最后只要再把成功监听器里拿到的数据处理就能使用了。

    post传到服务器上时已经是json格式,接着在服务器里处理,返回的也要是json格式的数据,否则会导致数据错误(无法转化成JSONObject格式)。
    (!所以我用php写的后台来接受数据时,无法用$_POST来接收上传的数据)

    最后,别忘了把这些请求加到队列中。

    requestQueue.add(request);

(2)图片数据的处理

  1. ImageRequest 图片请求
    ImageRequest与前面的request用法差不多,都是把请求扔到RequestQueue队列里。

    ImageRequest imageRequest = new ImageRequest(url,
    new Listener<Bitmap>() { @Override
    public void onResponse(Bitmap bitmap) {
    // TODO Auto-generated method stub
    } }, maxWidth, maxHeight, decodeConfig, new ErrorListener() { @Override
    public void onErrorResponse(VolleyError arg0) {
    // TODO Auto-generated method stub
    Log.e(TAG, "ErrorStatus: " + arg0.toString());
    }
    });

    可以看到,ImageRequest的构造函数能接收六个参数,第一个参数就是图片的URL地址。第二个参数是图片请求成功的回调, 这里我们可以把返回的Bitmap参数设置到ImageView中。第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩。第五个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而 RGB_565则表示每个图片像素占据2个字节大小。第六个参数是图片请求失败的回调,这里我们可以在请求失败时在ImageView中显示一张默认图片。

    最后,把请求放入队列中。

    requestQueue.add(request);
  2. ImageLoader 更加强大的网络图片请求
    ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。直接上代码吧
            ImageLoader imageLoader = new ImageLoader(requestQueue,
    new BitmapCache());//新建一个ImageLoader,传入requestQueue和图片缓存类
    ImageListener listener = ImageLoader.getImageListener(imageView,
    default_image, failed_image);//参数分别为要显示的图片控件,默认显示的图片(用于图片未下载完时显示),下载图片失败时显示的图片
    imageLoader.get(url, listener, maxWidth, maxHeight);//开始请求网络图片

    可以看到,ImageLoader的构造函数接收两个参数,第一个参数就是RequestQueue对象,第二个参数是一个ImageCache对象,我们通过调用ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,getImageListener()方法接收三个参数,第一个参数指定用于显示图片的ImageView控件,第二个参数指定加载图片的过程中显示的图片,第三个参数指定加载图片失败的情况下显示的图片。最后,调用ImageLoader的get()方法来加载图片。

    图片缓存类代码如下:

    public class BitmapCache implements ImageCache {
    
        private LruCache<String, Bitmap> mCache;
    
        public BitmapCache() {
    int maxSize = 10 * 1024 * 1024;// 10M的缓存
    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) {
    // TODO Auto-generated method stub
    return mCache.get(url);
    } @Override
    public void putBitmap(String url, Bitmap bitmap) {
    // TODO Auto-generated method stub
    mCache.put(url, bitmap);
    } }
  3. NetworkImageView 网络图片加载控件
    除了上面的两种加载图片以外,volley还提供了一个继承ImageView的控件给我们使用。我们可以把NetworkImageView控件放入布局文件中然后就能调用了。
    <com.android.volley.toolbox.NetworkImageView
    android:id="@+id/network_image_view"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_gravity="center_horizontal"
    />

    先从布局中获得控件的控制权,

    networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);

    最后在设置一些相关的属性

    networkImageView.setDefaultImageResId(R.drawable.default_image);
    networkImageView.setErrorImageResId(R.drawable.failed_image);
    networkImageView.setImageUrl(url,imageLoader);

    setImageUrl()方法接收两个参数,第一个参数用于指定图片的URL地址,第二个参数则是前面创建好的ImageLoader对象。其中的imageLoader需要我们自己创建(就是上一个图片加载方法的imageLoader),将其作为参数传进去。其实NetworkImageView控件和用ImageLoader加载图片性质上都是一样的。

(3)自定义数据的处理

自定义的网络请求可以继承volley的Request类来重写,比如说XML格式的请求。其中最重要的是Request类中的parseNetworkResponse方法。

像StringRequest中的parseNetworkResponse方法

        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));

重点是怎么将response.data转化成相应的字符格式。

像JsonObject里面的方法

@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}

先将传过来的数据转化成String格式,再根据情况转成Json或者是XML。

如我们自定义的XMLRequest可以写成这样子。

@Override
protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {
try {
String xmlString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlString));
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));
}
}

三、结束语

Volley给我们在网络传输的方面提供了很大的方便,尤其是网络图片加载的部分。除此之外,我们可以从volley的源代码入手可以学习到更多的知识,比如说如何构建一个完善的框架,如何使框架具有良好的扩展性。所以我建议有空的话可以把源代码下载过来仔细体味一番...

源码的分析在下面的文章链接中。

参考文章:(1) Android Volley完全解析 http://blog.csdn.net/guolin_blog/article/details/17482095

               (2)Android应用开发:网络工具——Volley(一) http://blog.csdn.net/airk000/article/details/38983051

(3)Android应用开发:网络工具——Volley(二) http://blog.csdn.net/airk000/article/details/39003587

(4)github上的volley库分析 https://github.com/android-cn/android-open-project-analysis/tree/master/volley

Demo地址:这是github上一个开源分析项目(@android-cn)里面一位成员(@grumoon包括上面的volley库分析)所写的一个volley demo地址 https://github.com/android-cn/android-open-project-demo/tree/master/volley-demo

========================================

作者:cpacm

地址:http://www.cnblogs.com/cpacm/p/4193011.html

Volley框架的使用的更多相关文章

  1. Android Volley框架的使用(1)

    在Android开发中,经常要通过HTTP请求访问网络.为了使通过HTTP请求访问网络的过程更加简单,2013年提出了新的HTTP通信框架--Volley.Volley使用起来非常简单,适用于网络访问 ...

  2. 安卓中自定义并使用Volley框架请求网络

    大家好,今天我们讲一下如何使用Volley框架请求网络,为何要使用Volley框架,这就要先说一下使用Volley框架请求网络的优点了,volley是易于定制的,即你可以根据需求来设定volley框架 ...

  3. 技术文档--volley 框架

    Volley 框架 参考文档:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f73e7e808c027fa ...

  4. Android Volley 框架的使用(一)

    为什么要使用Volley框架 开发android应用很多时候都要涉及网络操作,Android SDK中提供了HttpClient 和 HttpUrlConnection两种方式用来处理网络操作,但当应 ...

  5. Volley框架的流程图分析

          接着上一篇Volley框架的使用,这一篇主要主要讲Volley框架运作的原理.主要使用流程图来叙述,简单的分析了整个流程的过程,具体的请参考源代码或者查看我上一篇在文章末尾添上的链接. 一 ...

  6. Android Volley框架的使用(三)

     此博文源码下载地址  https://github.com/Javen205/VolleyDemo.git Image Request 为了更方便的使用Volley中的图片请求,我们同样先在Voll ...

  7. Android Volley框架的使用(二)

     此博文源码下载地址  https://github.com/Javen205/VolleyDemo.git 使用请求队列RequestQueue Volley中的Request都需要添加到Reque ...

  8. Android网络通信Volley框架源代码浅析(三)

    尊重原创 http://write.blog.csdn.net/postedit/26002961 通过前面浅析(一)和浅析(二)的分析.相信大家对于Volley有了初步的认识,可是假设想更深入的理解 ...

  9. 安卓高级2 Volley框架的使用案例

    初始化类: MyApp.java package qianfeng.com.day37_volley_pull.app; import android.app.Application; import ...

  10. 【安卓网络请求开源框架Volley源码解析系列】定制自己的Request请求及Volley框架源码剖析

    通过前面的学习我们已经掌握了Volley的基本用法,没看过的建议大家先去阅读我的博文[安卓网络请求开源框架Volley源码解析系列]初识Volley及其基本用法.如StringRequest用来请求一 ...

随机推荐

  1. php strrpos()与strripos()函数不同之处在哪里呢

    strripos() 函数 定义和用法strripos() 函数查找字符串在另一个字符串中最后一次出现的位置.如果成功,则返回位置,否则返回 false.语法strrpos(string,find,s ...

  2. quick lua 3.3常用方法和学习技巧之transition.lua

    transition.lua主要是动作相关的操作. -------------------------------- -- @module transition --[[-- 为图像创造效果 ]] l ...

  3. HDU 5688:2016"百度之星" - 资格赛 Problem D

    原文链接:https://www.dreamwings.cn/hdu5688/2650.html Problem D Time Limit: 2000/1000 MS (Java/Others)    ...

  4. 如何使用VS2013对C++进行编程

    https://msdn.microsoft.com/zh-cn/library/bb384842.aspx

  5. stoneniqiu 理想就是自己喜欢做,并对社会和他人都有意义的事情!

    H5嵌入原生开发小结----兼容安卓与ios的填坑之路 2016-11-19 08:29 by stoneniqiu, 1038 阅读, 8 评论, 收藏, 编辑 一开始听说开发H5,以为就是做适配现 ...

  6. 【leetcode❤python】 396. Rotate Function

    #-*- coding: UTF-8 -*- #超时#        lenA=len(A)#        maxSum=[]#        count=0#        while count ...

  7. My favorite bit torrent client for Ubuntu

    Deluge Bit Torrent ClientDeluge is among my favorite bit torrent clients for Ubuntu. It is fast, sli ...

  8. php : 单例设计演示

    单例 : 保证只有一个实例 <?php /* * 单例设计 */ // 单例: 只能"创造"出它的一个对象实例 class Single{ // 第一步: 私有化构造方法 p ...

  9. HTML基础(2)

    常见标签 1.img标签 <img src="图片地址" alt="图片名"/>  图片(单标签) alt属性 是图片名字,是给百度搜索引擎抓取使用 ...

  10. IE6/7常用的hack

    hack基础: IE6: _selector{property:value;} selector{property:value;property:value !important;} //IE6 不支 ...