• 技术文章 >Java >java教程

    Android开发—Volley具体的使用详解

    黄舟黄舟2017-03-10 09:26:49原创764
    0. 前言

    Android系统中主要提供了HttpURLConnectionHttpClient进行网络通信,但是如果不对其进行封装就很容易就会写出重复代码。因此一些Android网络通信框架应运而生, Volley就是其中的佼佼者,Volley不仅可以进行HTTP通信,也可以轻松加载网络上的图片Volley设计的初衷就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。原因总结如下:

    1Volley的网络请求线程池默认为4。因此只能并发进行4个请求(多了排队),容易被4个较大文件的下载任务阻塞其余请求

    2RequestparseNetWorkResponse()方法返回byte[]类型,需要把传输到的数据读到内存中。如果文件过大,容易引发OOM

    1. Volley的基本使用

    1.1 HTTP GET请求

    首先在AS中导入Volley的jar包

    RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
    StringRequest stringRequest_get = new StringRequest("http://www.baidu.com",
           new Response.Listener<String>() {
             @Override
             public void onResponse(String response) {
                   Log.d("TAG", response);
             }
          }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("TAG", error.getMessage(), error);
                }
      });
    mQueue.add(stringRequest);

    StringRequest的构造函数需要传入三个参数,第一个是URL地址,第二/三个参数是服务器响应成功/失败的回调。若成功则将返回的html代码转为String打印出log


    1.2 HTTP POST请求

    RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
    StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {  
        @Override  
        protected Map<String, String> getParams() throws AuthFailureError {  
            Map<String, String> map = new HashMap<String, String>();  
            map.put("params1", "value1");  
            map.put("params2", "value2");  
            return map;  
        }  
    };  
    mQueue.add(stringRequest);


    当发出POST请求的时候,Volley会尝试调用StringRequest的父类中的getParams()方法来获取POST参数,因此我们需要在StringRequest中重写getParams()方法,设置POST参数即可。


    1.3 JsonRequest

    StringRequest一样,JsonRequest也是继承自Request类的 JsonRequest是一个抽象类,有两个子类JsonObjectRequestJsonArrayRequest,前者用于请求一段JSON数据的,后者用于请求一段JSON数组。下面是使用前者进行一段Json请求的范例代码。


    //队列初始化以及request加入队列略
    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null,  
            new Response.Listener<JSONObject>() {  
                @Override  
                public void onResponse(JSONObject response) {  
                    Log.d("TAG", response.toString());  
                }  
            }, new Response.ErrorListener() {  
                @Override 
                public void onErrorResponse(VolleyError error) {  
                    Log.e("TAG", error.getMessage(), error);  
                }  
    });



    1.4 ImageRequest

    Volley支持对图片的加载,因为ImageRequest也是继承自Request类,因此用法也大同小异。下面直接传入图片url,返回数据后内部解析为bitmap,最后设置给ImageView。否则设置默认图片。

    ImageRequest imageRequest = new ImageRequest(url_image,  
            new Response.Listener<Bitmap>() {  
                @Override  
                public void onResponse(Bitmap response) {  
                    imageView.setImageBitmap(response);  
                }  
            }, 0, 0, Config.RGB_565, new Response.ErrorListener() {  
                @Override  
                public void onErrorResponse(VolleyError error) {  
                    imageView.setImageResource(R.drawable.default_image);  
                }  
    });

    需要注意的是,第三/四个参数用于指定允许图片最大的宽/,若网络图片的实际宽高大于该设定值,则会对图片进行压缩,指定成0的话就表示不进行压缩。第五个参数用于指定图片的颜色属性Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。不过这种加载图片的方式并不被推荐,因为下面有更好的。



    1.5 ImageLoader

    ImageLoader基于ImageRequest实现,并且更加智能,多出了帮图片缓存的功能,还可以过滤掉重复的请求链接。但是ImageLoader已经不再继承自Request类。

    //mQueue初始化略
    ImageLoader imageLoader = new ImageLoader(mQueue, new BitmapCache());
    ImageListener listener = ImageLoader.getImageListener(imageView,  R.drawable.default_image, 
    R.drawable.failed_image);  
    imageLoader.get(url_image, listener, 200, 200);  //限制最大宽高
    public class BitmapCache implements ImageCache { 
        //内部使用LRU实现 
        private LruCache<String, Bitmap> mCache;  
    public BitmapCache() {  
    	   //缓存图片的大小设置为10M
            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);  
        }  
    }


    第二行构造一个ImageLoader对象,其中第二个参数是一个ImageCache对象,参数二为自定义的用户缓存的类BitmapCache,该类继承了ImageCache。第三行获取一个ImageListener对象,传入参数比较简单,看名字就知道了。第四行调用ImageLoaderget()方法来加载图片。

    1.6 NetworkImageView

    这是第三种加载图片的方式,相对来说也是被用的比较多的方式。NetworkImageView继承自ImageView的,在原生的基础之上加入了加载网络图片的功能。用法仍旧是先创建一个RequestQueue对象和一个ImageLoader对象。接下来是在xml中定义我们的NetworkImageView,宽高表示裁剪到此宽高,wrap_content表示不裁剪。

    <com.android.volley.toolbox.NetworkImageView   
            android:id="@+id/network_image_view"  
            android:layout_width="100dp"  
            android:layout_height="100dp"/>

    Activity中获取到NetworkImageView实例后,就可以调用它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法来分别设置加载时显示的图片,加载失败时显示的图片,以及目标图片的URL地址。

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


    2. 自定义Request

    在网络上传输的数据常用到XMLJSON格式,那么如果想要请求一条XML/JSON格式的数据就需要拓展我们的Volley

    2. 1 XMLRequest

    public class StringRequest extends Request<String> {  
        private final Listener<String> mListener;  
        public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) {  
            super(method, url, errorListener);  
            mListener = listener;  
        }  
        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));  
        }  
    }

    拓展之前先要看一下原有的Request的子类是如何实现的,上面以StringRequest为例。StringRequest中提供了两个有参的构造函数,参数包括请求类型,请求地址,以及响应回调等,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中处理的。

    由于Request类中的deliverResponse()parseNetworkResponse()是两个抽象方法,因此StringRequest中对这两个方法进行了实现。前者调用了mListener中的onResponse()方法,并将response内容传入即完成了将服务器响应的数据进行回调。后者对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponsedata变量中(前言中在Volley为什么不适合大文件下载就讲到了),这里将数据取出然后组装成一个String,并传入Responsesuccess()方法中。

    在了解了StringRequest之后,我们自定义实现我们的XMLRequest

    public class XMLRequest extends Request<XmlPullParser> {  
        private final Listener<XmlPullParser> mListener;  
        public XMLRequest(int method, String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {  
            super(method, url, errorListener);  
            mListener = listener;  
        }  
      
        public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) {  
            this(Method.GET, url, listener, errorListener);  
        }  
      
        @Override  
        protected void deliverResponse(XmlPullParser response) {  
            mListener.onResponse(response);  
        }  
    
        @Override  
        protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {  
            try {  
    		  //先转为字符串
                String xmlString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));  
    		  //重点在于解析xml
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();  
                XmlPullParser xmlPullParser = factory.newPullParser();  
                xmlPullParser.setInput(new StringReader(xmlString));
    		  //返回XmlPullParser实例
                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));  
            }  
        }    
    }  
    
    //使用我们的XMLRequest
    XMLRequest xmlRequest = new XMLRequest( url_xml, new Response.Listener<XmlPullParser>() {  
                @Override  
                public void onResponse(XmlPullParser response) {  
                    try {  
                        int eventType = response.getEventType();  
                        while (eventType != XmlPullParser.END_DOCUMENT) {  
                            switch (eventType) {  
                            case XmlPullParser.START_TAG:  
                                String nodeName = response.getName();  
                                if (WANTED_TAG.equals(nodeName)) {  
                                    String pName = response.getAttributeValue(0);  
                                    Log.d("TAG", "pName is " + pName);  
                                }  
                                break;  
                            }  
                            eventType = response.next();  
                        }  
                    } catch (XmlPullParserException e) {  
                        e.printStackTrace();  
                    } catch (IOException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }, new Response.ErrorListener() {  
                @Override  
                public void onErrorResponse(VolleyError error) {  
                    Log.e("TAG", error.getMessage(), error);  
                }  
            });


    2. 2 GsonRequest

    用过Gson的都知道Gson解析有多方便,这里可以把VolleyGson结合在一起吗?当然可以。重写代码基本上大同小异。前提是先导入Gson的jar包

    public class GsonRequest<T> extends Request<T> {  
        private final Listener<T> mListener;  
        private Gson mGson;  
        private Class<T> mClass;  
        public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) {  
            super(method, url, errorListener);  
            mGson = new Gson();  
            mClass = clazz;  
            mListener = listener;  
        }  
      
        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 jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
    		  //结合Gson解析  
                return Response.success(mGson.fromJson(jsonString, mClass),  HttpHeaderParser.parseCacheHeaders(response));  
            } catch (UnsupportedEncodingException e) {  
                return Response.error(new ParseError(e));  
            }  
        }  
      
        @Override  
        protected void deliverResponse(T response) {  
            mListener.onResponse(response);  
    }  
    }  
    
    //使用我们的GsonRequest
    GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(url_json,YourClass.class,  
            new Response.Listener<Weather>() {  
                @Override  
                public void onResponse(YourClass obj) {  
    			//这里获得obj对应的json中的数据
                }  
            }, new Response.ErrorListener() {  
                @Override  
                public void onErrorResponse(VolleyError error) {  
                    Log.e("TAG", error.getMessage(), error);  
                }  
            });

    以上就是Android开发—Volley具体的使用详解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:PHP,Android,Volley
    上一篇:Android开发—Volley源码的详细分析 下一篇:Android开发— 热修复Tinker源码的简单介绍
    PHP编程就业班

    相关文章推荐

    • 图文详解Java数据结构与算法• 带你搞懂JAVA反射机制(总结分享)• 深入解析JAVA中字符串常量池和缓冲池理解与作用• 归纳整理JAVA学习之流程控制• 详细解析Java集合框架

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网