Volley学习总结

Volley学习小结

1、概述

volley英文即是“齐射,并发”,是谷歌在2013年推出的网络通信库,有如下特点:

【1】通信更快,更简单

【2】Get、Post网络请求以及网络数据图像的高效的异步请求

【3】对网络优先级排序处理

【4】网络请求缓存,可以将上次数据进行简单缓存

【5】可以多级别取消请求

【6】可以和Activity生命周期的联动,在Activity销毁时可以结束网络请求操作


Volley在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。

2、Volley框架使用之网络请求

【Volley的get和post请求方式的使用】

也是对android原生的get和psot进行了二次封装和优化,首先要挑选一个合适的请求对象

StringRequest:对请求数据结果类型不确定的情况下使用,该类型可以涵盖后面2种类型

JsonObjectRequest:确定是jsonObject时使用

JsonArrayRequest:确定是jsonArray时使用


【Volley的网络请求队列建立和取消】

首先要建立一个全局的请求队列,每次建立的请求加入到这个全局队列中,这样方便同意添加删除等管理

【Volley与Activity生命周期的联动】

将网络请求与Activity绑定在了一起,防止当Activity销毁时请求依然存在造成内存溢出,通常是将请求设置Tag标签,在onStop()中执行取消请求

【Volley的简单二次回调封装】

满足全局使用的一个方式可控,可自定义定制需求

在写代码之前首先要找到volley的jar包http://download.****.net/detail/inquisitive_plus/8488223#comment ,然后如何导入jar包到Android Studio中参考

http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html

【代码实现】

这里给出一些关键代码,完整代码会在最后给出

Volley请求队列需要一个全局的,因此我们需要把他写到一个全局的Apllication中

<span style="font-size:18px;">public class MyApplication extends Application {
    //定义全局的网络请求队列
    public static RequestQueue queues;
    @Override
    public void onCreate() {
        super.onCreate();
        queues = Volley.newRequestQueue(getApplicationContext());
    }
    //获取请求队列
    public static RequestQueue getHttpQueues(){
        return queues;
    }
}</span>

然后在MAinActivity中给出StringResponse的方式,这里主要有四个参数 请求方式,url,请求成功回调函数,请求失败回调函数

Get方式URL直接携带参数

Get:String方式

<span style="font-size:18px;">private void Volley_StringGet() {
        /*这里使用StringRequets*/
        String url = "http://ip.taobao.com/service/getIpInfo.php?ip=125.71.229.221";
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show();

            }
        });
        /*请求对象设置Tag标签,并加入全局队列*/
        request.setTag("StringGet");
        MyApplication.getHttpQueues().add(request);

    }</span>
Get:Json方式
<span style="font-size:18px;">private void Volley_JsonGet() {
        /*这里使用JsonRequets*/
        String url = "http://ip.taobao.com/service/getIpInfo.php?ip=125.71.229.221";
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject js) {
                Toast.makeText(MainActivity.this, js.toString(), Toast.LENGTH_LONG).show();

            }
        },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {
                        Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show();
                    }
                });
        /*请求对象设置Tag标签,并加入全局队列*/
        request.setTag("JsonGet");
        MyApplication.getHttpQueues().add(request);

    }</span>

Post:String方式

这里注意psot方式中URL不直接携带,StringPsot需要使用getParams()设置

<span style="font-size:18px;">private void Volley_StringPost() {
        /*这里使用StringRequets*/
        String url = "http://ip.taobao.com/service/getIpInfo.php?";
        StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show();

            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                //这里需要设置post的参数
                Map<String, String> hashMap = new HashMap<String, String>();
                hashMap.put("ip", "125.71.229.221");
                return hashMap;
            }
        };
        //post请求需要单独实现
        /*请求对象设置Tag标签,并加入全局队列*/
        request.setTag("StringPost");
        MyApplication.getHttpQueues().add(request);
    }</span>

Post :Json方式

这种方式首先需要HashMap来装参数,然后把新建jsonObj携带该参数即可使用,后来测试时发现这里使用的是淘宝IP查询接口不支持post方式,但是StringPost可以,jsonPost貌似不可以,不过操作方式是对的,你也可以换个其他结口试试。

<span style="font-size:18px;"> private void Volley_JsonPost() {
        /*这里使用JsonRequets*/
        String url = "http://ip.taobao.com/service/getIpInfo.php?";

        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("ip", "125.71.229.222");
        JSONObject jsonParams = new JSONObject(hashMap);

        JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, jsonParams, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                Toast.makeText(MainActivity.this, jsonObject.toString(), Toast.LENGTH_LONG).show();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Toast.makeText(MainActivity.this, volleyError.toString(), Toast.LENGTH_LONG).show();
            }
        }) {

            @Override
            public Map<String, String> getHeaders() {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Accept", "application/json");
                headers.put("Content-Type", "application/json; charset=UTF-8");
                return headers;
            }
        };
        /*请求对象设置Tag标签,并加入全局队列*/
        request.setTag("JsonPost");
        MyApplication.getHttpQueues().add(request);
    }</span>


Volley与Activity进行联动:

当Activity进行关闭的时候需要在onStop方法处理,yourTag则是你设置关联的Tag

<span style="font-size:18px;"> @Override
    protected void onStop() {
        super.onStop();
        MyApplication.getHttpQueues().cancelAll("yourTag");
    }</span>

Volley的简单的二次封装我们将它写在utils包中

不如我们在请求失败都要加一个toast弹窗或者请求成功加一些其他的提示,需要在每次使用的地方都加上,比较麻烦,我们可以做一个二次封装以便全局统一使用

主要封装请求成功和请求失败的回调,这里以StringRequest为例

首先需要一个接口Interface

<span style="font-size:18px;">public abstract class VolleyStringReqItf {
    public Context context;
    public static Response.Listener<String> listener;
    public static Response.ErrorListener errorListener;

    //成功和失败的回调函数
    public abstract void onMySuccess(String result);

    public abstract void onMyError(VolleyError error);

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

    public Response.Listener<String> loadingListener() {
        listener = new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                onMySuccess(response);
            }
        };
        return listener;
    }

    public Response.ErrorListener errorListener() {
        errorListener = new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                onMyError(volleyError);
            }
        };
        return errorListener;
    }
}
</span>

然后是我们自定义的StringRequest,注释很详细
<span style="font-size:18px;">/**
 * Created by ELVIS on 2015/11/7.
 */
public class VolleyStrRequest {
    public static StringRequest stringRequest;
    public static Context context;

    public static void RequestStrGet(Context context, String url, String tag, VolleyStringReqItf vif) {
        //取消当前tag的volley请求防止重复请求
        MyApplication.getHttpQueues().cancelAll(tag);

        stringRequest = new StringRequest(Request.Method.GET, url, vif.loadingListener(), vif.errorListener());
        stringRequest.setTag(tag);
        MyApplication.getHttpQueues().add(stringRequest);
        //开启请求
        MyApplication.getHttpQueues().start();

    }

    public static void ReqestStrPost(Context context, String url, String tag, final HashMap<String, String> params, VolleyStringReqItf vif) {
        MyApplication.getHttpQueues().cancelAll(tag);

        stringRequest = new StringRequest(Request.Method.POST, url, vif.loadingListener(), vif.errorListener()) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return params;
            }
        };
        stringRequest.setTag(tag);
        MyApplication.getHttpQueues().add(stringRequest);
        MyApplication.getHttpQueues().start();
    }
}
</span>

这样使用起来就比较方便了,当然你也可以自定义自己的其他的VolleyRequest

3、Volley框架使用之加载图片的用法

【缓存功能简单介绍】

图片加载缓存主要使用了LruCache和ImageCache

【加载网络图片及监听】

主要是NetworkImageView

3.1、使用ImageRequest来请求网络图片

ImageRequest能够处理单张图片,返回bitmap。ImageReques通常有5个参数(url,成功listtener,加载图片宽度设置,加载图片高度设置,bitmap配置,失败listener),当加载图片宽高都为0表示按照原图大小加载

<span style="font-size:18px;"> private void initView() {
        iv_img = (ImageView) findViewById(R.id.iv_img);
        String url = " http://h.hiphotos.baidu.com/image/pic/item/d53f8794a4c27d1e3584e91b1fd5ad6edcc4384b.jpg";
        ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap bitmap) {
                iv_img.setImageBitmap(bitmap);

            }
        }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Toast.makeText(ImageActivity.this, "Failure", Toast.LENGTH_SHORT).show();
            }
        });
        MyApplication.getHttpQueues().add(request);
    }</span>

3.2、使用ImageLoader

    ImageLoader这个类需要一个Request的实例以及一个ImageCache的实例。图片通过一个URL和一个ImageListener实例的get()方法就可以被加载。ImageLoader会检查ImageCache,而且如果缓存里没有图片就会从网络上获取。
    Volley的ImageCache接口允许你使用你喜欢的Lru缓存实现。不幸的是Volley没有提供默认的实现。我们需要自己实现一个Bitcache
    ImageCache接口有两个方法,getBitmap(String url)和putBitmap(String url, Bitmap bitmap).这两个方法足够简单直白,他们可以添加任何的缓存实现。

BItMapCache.java

<span style="font-size:18px;">public class BitmapCache implements ImageLoader.ImageCache {

    public LruCache<String, Bitmap> cache;
    public static final int MAX = 5 * 1024 * 1024;

    public BitmapCache() {
        cache = new LruCache<String, Bitmap>(MAX) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight();
            }
        };
    }

    @Override
    public Bitmap getBitmap(String s) {
        return cache.get(s);
    }

    @Override
    public void putBitmap(String s, Bitmap bitmap) {
        cache.put(s, bitmap);
    }
}
</span>

使用   ImageLoader,其中getImgListner

        // imageView是一个ImageView实例  
        // ImageLoader.getImageListener的第二个参数是默认的图片resource id  
        // 第三个参数是请求失败时候的资源id,可以指定为0

<span style="font-size:18px;">private void initViewImgLoader() {
        Toast.makeText(ImageActivity.this, "ImgLoader方式", Toast.LENGTH_SHORT).show();
        String url = "http://image.tianjimedia.com/uploadImages/2012/090/063N2L5N2HID.jpg";
        //ImageLoader
        ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(), new BitmapCache());
        ImageLoader.ImageListener listener = ImageLoader.getImageListener(iv_img, R.mipmap.ic_launcher, R.mipmap.ic_launcher);
        loader.get(url, listener);
    }</span>

3.3、使用NetworkImageView方式

NetworkImageView 继承了 ImageView,并且在内部添加了

 

<span style="font-size:18px;">    public void setImageUrl(String url, ImageLoader imageLoader) {}  </span>

这里可以看出,使用NetworkImageView时候我们需要跟ImageLoader配合使用,而且还多了加载前默认图片和加载失败图片的方法

<span style="font-size:18px;">public void setDefaultImageResId(int defaultImage) {  
mDefaultImageId = defaultImage;  
}  
/** 
* Sets the error image resource ID to be used for this view in the event that the image 
* requested fails to load. 
*/  
public void setErrorImageResId(int errorImage) {  
mErrorImageId = errorImage;  
} </span>

使用代码:

<span style="font-size:18px;">private void initViewNetWorkImg() {
        Toast.makeText(ImageActivity.this, "NetWorkImg方式", Toast.LENGTH_SHORT).show();
        netImgView = (NetworkImageView) findViewById(R.id.netWorkImg);
        String url = "http://new.aliyiyao.com/UpFiles/Image/2011/01/13/nc_129393721364387442.jpg";
        ImageLoader loader = new ImageLoader(MyApplication.getHttpQueues(), new BitmapCache());
        netImgView.setDefaultImageResId(R.mipmap.ic_launcher);
        netImgView.setErrorImageResId(R.mipmap.ic_launcher);
        netImgView.setImageUrl(url, loader);

    }</span>

demo地址http://download.****.net/detail/xsf50717/9251751


版权声明:如有转载请注明出处,谢谢~