Android working with Volley

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/

时间: 2024-10-17 04:52:51

Android working with Volley的相关文章

Android working with Volley Library

Volley提供了优美的框架,使得Android应用程序网络访问更容易和更快.Volley抽象实现了底层的HTTP Client库,让你不关注HTTP Client细节,专注于写出更加漂亮.干净的RESTful HTTP请求.另外,Volley请求会异步执行,不阻挡主线程. Volley提供的功能 简单的讲,提供了如下主要的功能: 1.封装了的异步的RESTful 请求API: 2.一个优雅和稳健的请求队列: 3.一个可扩展的架构,它使开发人员能够实现自定义的请求和响应处理机制: 4.能够使用外

Android中关于Volley的使用(十)对Request和Reponse的认识

我们知道,在网络Http通信中,一定会有一个Request,同样的,也一定会有一个Response,而我们在Volley中利用RequestQueue来添加请求之前,一定会先创建一个Request对象,比如StringRequest,JsonObjectRequest和ImageRequest等,如下分别是前面Demo中的JsonRequest和ImageRequest: JsonObjectRequest: public JsonObjectRequest(String url, JSONOb

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

这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影视信息,每一行是一个影片的信息,每一行中有一张电影的图片,电影的名字.评分.类型.年份等信息. 1.json数据 我们通过解析json然后拿到数据,这个json数据包含json数组.每一个json数组中是一个json对象,json对象中包含了电影的图片url地址.标题.年份.评分.类型等信息 JSO

ym—— Android网络框架Volley(实战篇)

转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持. 之前讲了ym-- Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看怎样把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQueue 仅仅须要一个对象就可以,new RequestQueue对象对资源一种浪费,我们应该在application.以及能够把取消请求的方法也在application进行统一管理,看下面代

【转】Android 网络通信框架Volley简介(Google IO 2013)

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Go

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

<a target=_blank href="https://android.googlesource.com/platform/frameworks/volley" style="font-family: Arial, Helvetica, sans-serif; box-sizing: border-box; background-image: initial; background-attachment: initial; background-color: rg

Android网络框架Volley

Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp 他们各有优劣,之前个人则比较喜欢用Android-async-http, 如今Google推出了官方的针对Android平台上的网络通信库,能使网络通信更快,更简单,更健壮,Volley在提供了高性能网络通讯功能的同时,对网络图片加载也提供了良好的支持,完全可以满足简单REST客户端的需求, 我们

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

这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 最终效果 这个ListView呈现了一些影视信息,每一行是一个影片的信息,每一行中有一张电影的图片,电影的名字.评分.类型.年份等信息. 1.json数据 我们通过解析json然后拿到数据,这个json数据包括json数组,每个json数组中是一个json对象,json对象中包括了电影的图片url地址.标题.年份.评分.类型等信息 JSON

Android网络通信库Volley简介

1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google I/O 2013上,Volley发布了.Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮.这是Volley名称的由来: a burst or emission of many things or a large amount at

Android 网络通信框架Volley简介(Google IO 2013)

Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded 1. 什么是Volley 在 这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于 AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的