关闭

一. Volley简介 Volley的中文翻译为“齐射、并发”,是在2013年的Google大会上发布的一款Android平台网络通信库,具有网络请求的处理、小图片的异步加载和缓存等功能,能够帮助

279人阅读 评论(0) 收藏 举报
分类:

一. Volley简介

Volley的中文翻译为“齐射、并发”,是在2013年的Google大会上发布的一款Android平台网络通信库,具有网络请求的处理、小图片的异步加载和缓存等功能,能够帮助 Android APP 更方便地执行网络操作,而且更快速高效。

在Google IO的演讲上,其配图是一幅发射火弓箭的图,有点类似流星。这表示,Volley特别适合数据量不大但是通信频繁的场景。见下图:

此处输入图片的描述

Volley 有如下的优点:

  • 自动调度网络请求;
  • 高并发网络连接;
  • 通过标准的 HTTP cache coherence(高速缓存一致性)缓存磁盘和内存透明的响应;
  • 支持指定请求的优先级;
  • 网络请求cancel机制。我们可以取消单个请求,或者指定取消请求队列中的一个区域;
  • 框架容易被定制,例如,定制重试或者回退功能;
  • 包含了调试与追踪工具;

Volley 不适合用来下载大的数据文件。因为 Volley 会保持在解析的过程中所有的响应。对于下载大量的数据操作,请考虑使用 DownloadManager。

在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如:android-async-http、retrofit、okhttp等。他们各有优劣,可有所斟酌地选择选择更适合项目的类库。

附录:

Volley的github地址:https://github.com/mcxiaoke/android-volley

Google I/O 2013 – Volley: Easy, Fast Networking for Android:https://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded

二. Volley jar包的导入

Volley 框架的核心代码是托管在 AOSP 仓库的 frameworks/volley 中,相关的工具放在 toolbox 下。

把 Volley 添加到项目中最简便的方法是 Clone 仓库,然后把它设置为一个 library project。

1) clone代码:

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

2)将代码编译成jar包:

android update project -p . ant jar

如无意外,将获得volley.jar包。

3)添加volley.jar到你的项目中:

可参考:http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html

备注:

附上我的volley.jar包的地址:http://pan.baidu.com/s/1sjSwCrV,方便大家直接下载使用。当然,Volley更新较快,还是希望大家能直接通过clone代码后进行编译。

三. Volley框架的详细使用:

Volley工作原理图如下:

图片转载自`https://bxbxbai.github.io/2014/09/14/android-working-with-volley/`

使用Volley框架实现网络数据请求主要有以下三个步骤:

  • 1.创建RequestQueue对象,定义网络请求队列;
  • 2.创建XXXRequest对象(XXX代表String,JSON,Image等等),定义网络数据请求的详细过程;
  • 3.把XXXRequest对象添加到RequestQueue中,开始执行网络请求。

3.1 创建RequestQueue对象

一般而言,网络请求队列都是整个APP内使用的全局性对象,因此最好写入Application类中:

public class MyApplication extends Application{
    // 建立请求队列
    public static RequestQueue queue;

    @Override
    public void onCreate() {
        super.onCreate();
        queue = Volley.newRequestQueue(getApplicationContext());
    }

    public static RequestQueue getHttpQueue() {
        return queue;
    }
}

这是,我们还需要修改AndroidManifest.xml文件,使APP的Application对象为我们刚定义的MyApplication,并添加INTERNET权限:

<uses-permission android:name="android.permission.INTERNET" />
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
</application>

3.2 创建XXXRequest对象并添加到请求队列中

Volley提供了JsonObjectRequest、JsonArrayRequest、StringRequest等Request形式:

  • JsonObjectRequest:返回JSONObject对象;
  • JsonArrayRequest:返回JsonArray对象;
  • StringRequest:返回String。

另外可以继承Request自定义Request。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // GET请求
        VolleyGet();

        // POST请求
        VolleyPost();
    }

    // 定义POST请求的方法
    private void VolleyPost() {
        // 请求地址
        String url = "http://ce.sysu.edu.cn/hope/";

        // 创建StringRequest,定义字符串请求的请求方式为POST,
        StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            // 请求成功后执行的函数
            @Override
            public void onResponse(String s) {
                // 打印出POST请求返回的字符串
                Toast.makeText(MainActivity.this, "POST: " + s, Toast.LENGTH_LONG).show();
            }
        }, new Response.ErrorListener() {
            // 请求失败时执行的函数
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        }){

            // 定义请求数据
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> hashMap = new HashMap<String, String>();
                hashMap.put("phone", "11111");
                return hashMap;
            }
        };
        // 设置该请求的标签
        request.setTag("abcPost");

        // 将请求添加到队列中
        MyApplication.getHttpQueue().add(request);
    }

    // 定义GET请求的方法
    private void VolleyGet() {
        // 定义请求地址
        String url = "http://ce.sysu.edu.cn/hope/";
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                // 打印出GET请求返回的字符串
                Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });

        // 设置该请求的标签
        request.setTag("abcGet");

        // 将请求添加到队列中
        MyApplication.getHttpQueue().add(request);
    }
}

输出:

// POST请求
POST: <厚朴网站首页源代码。。。>
// GET请求
GET: <厚朴网站首页源代码。。。>

3.3 关闭请求

3.3.1 关闭特定标签的网络请求:

// 网络请求标签为"abcGet"
public void onStop() {
    super.onStop();
    MyApplication.getHttpQueues.cancelAll("abcGet");
}

3.3.2 取消这个队列里的所有请求:

在activity的onStop()方法里面,取消所有的包含这个tag的请求任务。

@Override  
protected void onStop() {  
    super.onStop();  
    mRequestQueue.cancelAll(this);  
}

四. GET和POST请求工具库的封装

4.1 重写Application

因为网络请求队列相对于APP应用老说是全局对象,因此可以定义在全局中。为此,我们新建一个LIMSApplication,并让其继承自Application。

LIMSApplication.java文件:

public class LIMSApplication extends Application {
    public static RequestQueue volleyQueue;
    @Override
    public void onCreate() {
        super.onCreate();

        /* Volley配置 */
        // 建立Volley的Http请求队列
        volleyQueue = Volley.newRequestQueue(getApplicationContext());
    }

    // 开放Volley的HTTP请求队列接口
    public static RequestQueue getRequestQueue() {
        return volleyQueue;
    }
}

不要忘记在AndroidManifest.xml文件中修改Application的name和相应的网络请求权限:

<uses-permission android:name="android.permission.INTERNET" />
<application
    android:name=".LIMSApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
</application>

4.2 GET和POST请求的封装:

目前,VolleyRequestUtil工具库只包含了两个函数,分别获取GET和POST请求。

VolleyRequestUtil.java:

public class VolleyRequestUtil {

    public static StringRequest stringRequest;
    public static Context context;

    /*
    * 获取GET请求内容
    * 参数:
    * context:当前上下文;
    * url:请求的url地址;
    * tag:当前请求的标签;
    * volleyListenerInterface:VolleyListenerInterface接口;
    * */
    public static void RequestGet(Context context, String url, String tag, VolleyListenerInterface volleyListenerInterface) {
        // 清除请求队列中的tag标记请求
        LIMSApplication.getRequestQueue().cancelAll(tag);
        // 创建当前的请求,获取字符串内容
        stringRequest = new StringRequest(Request.Method.GET, url, volleyListenerInterface.responseListener(), volleyListenerInterface.errorListener());
        // 为当前请求添加标记
        stringRequest.setTag(tag);
        // 将当前请求添加到请求队列中
        LIMSApplication.getRequestQueue().add(stringRequest);
        // 重启当前请求队列
        LIMSApplication.getRequestQueue().start();
    }

    /*
    * 获取POST请求内容(请求的代码为Map)
    * 参数:
    * context:当前上下文;
    * url:请求的url地址;
    * tag:当前请求的标签;
    * params:POST请求内容;
    * volleyListenerInterface:VolleyListenerInterface接口;
    * */
    public static void RequestPost(Context context, String url, String tag, final Map<String, String> params, VolleyListenerInterface volleyListenerInterface) {
        // 清除请求队列中的tag标记请求
        LIMSApplication.getRequestQueue().cancelAll(tag);
        // 创建当前的POST请求,并将请求内容写入Map中
        stringRequest = new StringRequest(Request.Method.POST, url, volleyListenerInterface.responseListener(), volleyListenerInterface.errorListener()){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return params;
            }
        };
        // 为当前请求添加标记
        stringRequest.setTag(tag);
        // 将当前请求添加到请求队列中
        LIMSApplication.getRequestQueue().add(stringRequest);
        // 重启当前请求队列
        LIMSApplication.getRequestQueue().start();
    }
}

4.3 Volley请求(成功或失败)的监听事件封装:

封装Volley请求(成功或失败)的监听事件,见VolleyListenerInterface.java:

public abstract class VolleyListenerInterface {
    public Context mContext;
    public static Response.Listener<String> mListener;
    public static Response.ErrorListener mErrorListener;

    public VolleyListenerInterface(Context context, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        this.mContext = context;
        this.mErrorListener = errorListener;
        this.mListener = listener;
    }

    // 请求成功时的回调函数
    public abstract void onMySuccess(String result);

    // 请求失败时的回调函数
    public abstract void onMyError(VolleyError error);

    // 创建请求的事件监听
    public Response.Listener<String> responseListener() {
        mListener = new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                onMySuccess(s);
            }
        };
        return mListener;
    }

    // 创建请求失败的事件监听
    public Response.ErrorListener errorListener() {
        mErrorListener = new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                onMyError(volleyError);
            }
        };
        return mErrorListener;
    }
}

4.3 Volley图片加载库的封装:

Volley库还具有图片加载的功能。但适合小图片的异步加载,不适合于比较大的图片资源的请求。

Volley提供了多种Request方法,譬如ImageRequest、ImageLoader、NetWorkImageView。

网络图片资源的请求封装如下:

ImageLoaderUtil.java:

public class ImageLoaderUtil {

    /*
    * 通过ImageRequest来显示网络图片
    * */
    public static void setImageRequest(String url, final ImageView imageView) {
        ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap bitmap) {
                imageView.setImageBitmap(bitmap);
            }
        }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                imageView.setBackgroundResource(R.mipmap.ic_launcher);
            }
        });
        LIMSApplication.getRequestQueue().add(imageRequest);
    }

    /*
    * 通过ImageLoader来显示网络图片
    * */
    public static void setImageLoader(String url, ImageView imageView, int defaultImageResId, int errorImageResId) {
        ImageLoader loader = new ImageLoader(LIMSApplication.getRequestQueue(), new BitmapCache());
        ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(imageView, defaultImageResId, errorImageResId);
        loader.get(url, imageListener);
    }

    /*
    * 通过Volley的NetWorkImageView来显示网络图片
    * */
    public static void setNetWorkImageView(String url, NetworkImageView netWorkImageView, int defaultImageResId, int errorImageResId) {
        ImageLoader loader = new ImageLoader(LIMSApplication.getRequestQueue(), new BitmapCache());

        netWorkImageView.setDefaultImageResId(defaultImageResId);
        netWorkImageView.setErrorImageResId(errorImageResId);
        netWorkImageView.setImageUrl(url, loader);
    }
}

五. VolleyRequestUtil与ImageLoaderUtil的使用

5.1 用GET方式请求网络资源:

new VolleyRequestUtil().RequestGet(this, "http://ce.sysu.edu.cn/hope/", "hopePage", 
    new VolleyListenerInterface(this, VolleyListenerInterface.mListener, VolleyListenerInterface.mErrorListener) {
    // Volley请求成功时调用的函数
    @Override
    public void onMySuccess(String result) {
        Toast.makeText(this, s, Toast.LENGTH_LONG).show();
    }

    // Volley请求失败时调用的函数
    @Override
    public void onMyError(VolleyError error) {
        // ...
    }
});

输出:厚朴网站首页的源代码。

5.2 用POST方式请求网络资源:

new VolleyRequestUtil().RequestPOST(this, "http://ce.sysu.edu.cn/hope/", "hopePage", 
    new VolleyListenerInterface(this, VolleyListenerInterface.mListener, VolleyListenerInterface.mErrorListener) {
    // Volley请求成功时调用的函数
    @Override
    public void onMySuccess(String result) {
        Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
    }

    // Volley请求失败时调用的函数
    @Override
    public void onMyError(VolleyError error) {
        // ...
    }
});

输出:厚朴网站首页的源代码。

5.3 通过ImageRequest来显示网络图片:

// 参数分别为:请求图片的地址、图片的容器ImageView
ImageView imgView = (ImageView) findViewById(R.id.imgView);
        new ImageLoaderUtil().setImageRequest("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", imgView);

在布局文件中,定义ImageView:

<ImageView
        android:id="@+id/imgView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

5.4 通过ImageLoader来显示网络图片:

// 参数分别为:请求图片的地址、图片的容器ImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
new ImageLoaderUtil().setImageLoader("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", imgView, R.mipmap.default, R.mipmap.error);

在布局文件中,定义ImageView:

<ImageView
        android:id="@+id/imgView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

5.5 通过Volley的NetWorkImageView来显示网络图片:

// 参数分别为:请求图片的地址、图片的容器NetworkImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
NetworkImageView netWorkImageView = (NetworkImageView) findViewById(R.id.imgNetworkView);
        new ImageLoaderUtil().setNetWorkImageView("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", netWorkImageView, R.mipmap.default, R.mipmap.error);

在布局文件中,定义NetworkImageView:

<com.android.volley.toolbox.NetworkImageView  
               android:id="@+id/imgNetworkView"  
               android:layout_width="300dp"  
               android:layout_height="300dp"  
               android:layout_centerHorizontal="true"/>

六. 后记

该Volley的封装中,暂未考虑到图片和数据缓存。

有一些地方封装得仍不够抽象,有待完善。

非常欢迎读者能提出修改建议,一起进步。

原文地址:http://www.dengzhr.com/others/mobile/android/762

0
0
查看评论

Volley二次封装,实现网络请求缓存

Android目前很多同学使用Volley请求网络数据,但是Volley没有对请求过得数据进行缓存,因此需要我们自己手动缓存。 一下就是我的一种思路,仅供参考 NetWorkHelper---对Volley的封装,首先调用CacheManager.get(methodName, params)...
  • zxm317122667
  • zxm317122667
  • 2015-11-04 11:13
  • 4821

Volley高并发处理网络请求(No2)

这是我觉得比较好的第二遍,讲的详细到位,转载过来供大家学习参考 No 002:转载于点击打开链接 下面贴介绍和源码: .Volley简介 volley的英文意思为‘群发’、‘迸发’。Volley是2013年谷歌官方发布的一款Android平台上的网络通信库。Volley非常适合一些数据量不大,...
  • Demo006
  • Demo006
  • 2016-04-27 22:47
  • 1147

Volley的使用(一) get请求和获取网络图片

什么是Volley以及为什么使用Volley在我们android开发过程中不可避免的要进行网络访问,android为我们提供了两种方式来访问网络:HttpURLConnection和HttpClient 而使用这两种类来访问网络的时候仍然需要大量的代码来实现,而且对于不熟练的人来说很容易出错。 ...
  • baidu_31093133
  • baidu_31093133
  • 2016-05-06 00:05
  • 545

Volley源码解析(三)网络请求流程

volley封装的很好,使用起来很方便,在一篇博客中,我们学些了volley进行网络请求的三个步骤,以及请求不同格式定义不同的Request,但是对Volley的源码我们还不是很清楚,就让我们一起来阅读以下Volley的源码,将Volley的工作流程和工作原理梳理以下。首先我们看一下Volley官方...
  • chengshuyuan_uestc
  • chengshuyuan_uestc
  • 2016-06-24 19:10
  • 2890

弄明白android 网络库之Volley(一)

1、Volley是什么? Volley是Google 官方在2013 Android IO大会上推出的新网络通信框架, 一个使得android 网络通信更加容易并且迅速的HTTP库。它并且可以通过开放的AOSP仓库进行使用。 它有以下特性: (1)自动调度网络请求; (2)支持多并发的网络连接; (...
  • linfeng24
  • linfeng24
  • 2014-12-21 21:59
  • 1066

Volley高并发处理网络请求(No1)

这是我的第一篇博客,那些地方不规范多多包涵,声明转载他人的。最近学习了Volley框架,感觉在处理网络轻量级数据时特别好用,所以将自己学习过程觉得好的2篇文章拿来分享!! No 001:转载于点击打开链接 Volley简介: Volley是google在13年I/O大会上发布的有关网络请求的框...
  • Demo006
  • Demo006
  • 2016-04-27 22:38
  • 1171

Volley 实现原理解析(转)

转自:https://github.com/android-cn/android-open-project-analysis/tree/master/volley Volley 实现原理解析 本文为 Android 开源项目实现原理解析 中 Volley 部分 项目...
  • fengqiaoyebo2008
  • fengqiaoyebo2008
  • 2015-01-21 09:40
  • 21786

使用Volley实现ListView异步加载图片

原文链接:Android Custom ListView with Image and Text using Volley 我(作者:Ravi Tamada)在之前的博文 中向大家介绍了一种自定义ListView的方法,其中ListView包含了一张缩略图和一些文本框,所有的数据通过...
  • Hander_Wei
  • Hander_Wei
  • 2015-04-15 18:37
  • 1812

Volley的缓存策略

再读Volley第一次看Volley的代码的时候只是大概地理清了它的结构而没有做细节上的记录,但是看了这两篇文章之后,面试后的总结和Android网络请求心路历程,发现Volley还有很多可以学习的地方,所以再次研读
  • CsL664867596
  • CsL664867596
  • 2016-03-14 21:23
  • 1763

Android 异步网络请求框架-Volley

Android 异步网络请求框架-Volley1. 功能介绍1.1. VolleyVolley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。 名字由来:a burst or emission of many things...
  • brian512
  • brian512
  • 2016-01-11 13:32
  • 3138
    个人资料
    • 访问:12514次
    • 积分:351
    • 等级:
    • 排名:千里之外
    • 原创:20篇
    • 转载:13篇
    • 译文:0篇
    • 评论:0条