Volley

一. Volley简介
1).Volley的中文翻译为“齐射、并发”,是在2013年的Google大会上发布的一款Android平台网络通信库,具有网络请求的处理、小图片的异步加载和缓存等功能,能够帮助 Android APP 更方便地执行网络操作,而且更快速高效。
2).在Google IO的演讲上,其配图是一幅发射火弓箭的图,有点类似流星。这表示,Volley特别适合数据量不大但是通信频繁的场景。见下图:
附图

volley的工作原理
附图

二.Volly的优点
1.高并发网络连接;
2.自动调度网络请求;
3.支持指定请求的优先级;
4.包含了调试与追踪工具;
5.框架容易被定制,例如,定制重试或者回退功能;
6.网络请求cancel机制。我们可以取消单个请求,或者指定取消请求队列中的一个区域;
7.通过标准的 HTTP cache coherence(高速缓存一致性)缓存磁盘和内存透明的响应;
但是
Volley 不适合用来下载大的数据文件。因为 Volley 会保持在解析的过程中所有的响应。对于下载大量的数据操作,请考虑使用 DownloadManager。

三.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包的地址:http://pan.baidu.com/s/1jHKm3qe 。Volley更新较快,还是希望大家能直接通过clone代码后进行编译。

四.Volley框架的使用

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

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

4.1 创建RequestQueue对象
1).创建全局Volley对象

public class App extends Application{

    // 建立请求队列
    public static RequestQueue sQueue;

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

    public static RequestQueue getHttpQueue(){
        return sQueue;
    }
}
<uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

2).创建XXXRequest对象并添加到请求队列中

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

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

Get请求:

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

            }
        });
        // 设置该请求的标签
        request.setTag("VolleyGet");
        // 将请求添加到队列中
        App.getHttpQueue().add(request);

    }
private void VolleyGetJson(){
        // 定义请求地址
        String url = "http://www.baidu.com";
        JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {

                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });
        objectRequest.setTag("getJson");
        App.getHttpQueue().add(objectRequest);
    }

Post请求:

private void VolleyPost() {
        // 定义请求地址
        String url = "http://www.baidu.com";
        StringRequest request = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        // response
                        Log.d("Response", response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // error
                    }
                }
        ) {
            // 定义请求数据
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("name", "xiaoming");

                return params;
            }
        };
        // 设置该请求的标签
        request.setTag("VolleyPost");
        // 将请求添加到队列中
        App.getHttpQueue().add(request);

    }

输出:百度首页源码。

其他方式:请求

PUT 请求:

private void VolleyPut() {
        // 定义请求地址
        String url = "http://www.baidu.com";
        StringRequest request = new StringRequest(Request.Method.PUT, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        // response
                        Log.d("Response", response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // error
                    }
                }
        ) {
            // 定义请求数据
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("name", "xiaoming");
                return params;
            }
        };
        // 设置该请求的标签
        request.setTag("VolleyPut");
        // 将请求添加到队列中
        App.getHttpQueue().add(request);
    }

DELETE 请求:

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

                    }
                });
        // 设置该请求的标签
        request.setTag("VolleyDelete");
        // 将请求添加到队列中
        App.getHttpQueue().add(request);
    }

关闭请求:
1).关闭指定的请求:

// 网络请求标签为"VolleyGet"
@Override  
public void onStop() {
    super.onStop();
    App.getHttpQueues.cancelAll("VolleyGet");
}

2).关闭这个队列里的所有请求:

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

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


五.封装
1).GET和POST请求的封装:
VolleyUtil.java:

public class VolleyUtil {

    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标记请求
        App.getHttpQueue().cancelAll(tag);
        // 创建当前的请求,获取字符串内容
        stringRequest = new StringRequest(Request.Method.GET, url, volleyListenerInterface.responseListener(), volleyListenerInterface.errorListener());
        // 为当前请求添加标记
        stringRequest.setTag(tag);
        // 将当前请求添加到请求队列中
        App.getHttpQueue().add(stringRequest);
        // 重启当前请求队列
        App.getHttpQueue().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标记请求
        App.getHttpQueue().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);
        // 将当前请求添加到请求队列中
        App.getHttpQueue().add(stringRequest);
        // 重启当前请求队列
        App.getHttpQueue().start();
    }
}

2).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;
    }
}

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);
            }
        });
        App.getHttpQueue().add(imageRequest);
    }

    /*
    * 通过ImageLoader来显示网络图片
    * */
    public static void setImageLoader(String url, ImageView imageView, int defaultImageResId, int errorImageResId) {
        ImageLoader loader = new ImageLoader(App.getHttpQueue(), 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(App.getHttpQueue(), new BitmapCache());

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

4).图片缓存

public class BitmapCache implements ImageCache {  

    private LruCache<String, Bitmap> mCache;  

    public BitmapCache() {  
        int maxSize = 10 * 1024 * 1024;  
        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) {  
        return mCache.get(url);  
    }  

    @Override  
    public void putBitmap(String url, Bitmap bitmap) {  
        mCache.put(url, bitmap);  
    }  

}  

六.封装使用
1).用GET方式请求网络资源:

new VolleyRequestUtil().RequestGet(this, "http://www.baidu.com", "标签", 
    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) {
        // ...
    }
});

2).用POST方式请求网络资源:

new VolleyRequestUtil().RequestPOST(this, "http://www.baidu.com", "标签", 
    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) {
        // ...
    }
});

3).通过ImageRequest来显示网络图片:

在布局文件中,定义ImageView:

<ImageView
        android:id="@+id/imgView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
ImageView imgView = (ImageView) findViewById(R.id.imgView);
        new ImageLoaderUtil().setImageRequest("http://b.hiphotos.baidu.com/album/s%3D1600%3Bq%3D90/sign=4f04be8ab8014a90853e42bb99470263/b8389b504fc2d562d426d1d5e61190ef76c66cdf.jpg?v=tbs", imgView);

4).通过ImageLoader来显示网络图片:

// 参数分别为:请求图片的地址、图片的容器ImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
new ImageLoaderUtil().setImageLoader("http://b.hiphotos.baidu.com/album/s%3D1600%3Bq%3D90/sign=4f04be8ab8014a90853e42bb99470263/b8389b504fc2d562d426d1d5e61190ef76c66cdf.jpg?v=tbs", imgView, R.mipmap.default, R.mipmap.error);

5).通过Volley的NetWorkImageView来显示网络图片:

在布局文件中,定义NetworkImageView:

<com.android.volley.toolbox.NetworkImageView  
               android:id="@+id/imgNetworkView"  
               android:layout_width="300dp"  
               android:layout_height="300dp"  
               android:layout_centerHorizontal="true"/>
// 参数分别为:请求图片的地址、图片的容器NetworkImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
NetworkImageView netWorkImageView = (NetworkImageView) findViewById(R.id.imgNetworkView);
        new ImageLoaderUtil().setNetWorkImageView("http://b.hiphotos.baidu.com/album/s%3D1600%3Bq%3D90/sign=4f04be8ab8014a90853e42bb99470263/b8389b504fc2d562d426d1d5e61190ef76c66cdf.jpg?v=tbs", netWorkImageView, R.mipmap.default, R.mipmap.error);

七.后记
有一些地方封装得仍不够抽象,有待完善。
非常欢迎读者能提出修改建议,一起进步。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值