0

0

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

黄舟

黄舟

发布时间:2017-03-10 09:26:49

|

1703人浏览过

|

来源于php中文网

原创

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() {
         @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


php商城系统
php商城系统

PHP商城系统是国内功能优秀的网上商城系统,同时也是一个商业的PHP开发框架,有多套免费模版,强大的后台管理功能,专业的网上商城系统解决方案,快速建设网上购物商城、数码商城、手机商城、办公用品商城等网站。 php商城系统v3.0 rc6升级 1、主要修复用户使用中出现的js未加载完报错问题,后台整改、以及后台栏目的全新部署、更利于用户体验。 2、扩展出,更多系统内部的功能,以便用户能够迅速找到需

下载

1.2  HTTP POST请求

RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Method.POST, url, listener, errorListener) {  
    @Override  
    protected Map getParams() throws AuthFailureError {  
        Map map = new HashMap();  
        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() {  
            @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() {  
            @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 mCache;  
public BitmapCache() {  
	   //缓存图片的大小设置为10M
        int maxSize = 10 * 1024 * 1024;  
        mCache = new LruCache(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表示不裁剪。

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 {  
    private final Listener mListener;  
    public StringRequest(int method, String url, Listener listener, ErrorListener errorListener) {  
        super(method, url, errorListener);  
        mListener = listener;  
    }  
    public StringRequest(String url, Listener listener, ErrorListener errorListener) {  
        this(Method.GET, url, listener, errorListener);  
    }  
  
    @Override  
    protected void deliverResponse(String response) {  
        mListener.onResponse(response);  
    }  
  
    @Override  
    protected Response 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 {  
    private final Listener mListener;  
    public XMLRequest(int method, String url, Listener listener, ErrorListener errorListener) {  
        super(method, url, errorListener);  
        mListener = listener;  
    }  
  
    public XMLRequest(String url, Listener listener, ErrorListener errorListener) {  
        this(Method.GET, url, listener, errorListener);  
    }  
  
    @Override  
    protected void deliverResponse(XmlPullParser response) {  
        mListener.onResponse(response);  
    }  

    @Override  
    protected Response 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() {  
            @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 extends Request {  
    private final Listener mListener;  
    private Gson mGson;  
    private Class mClass;  
    public GsonRequest(int method, String url, Class clazz, Listener listener, ErrorListener errorListener) {  
        super(method, url, errorListener);  
        mGson = new Gson();  
        mClass = clazz;  
        mListener = listener;  
    }  
  
    public GsonRequest(String url, Class clazz, Listener listener, ErrorListener errorListener) {  
        this(Method.GET, url, clazz, listener, errorListener);  
    }  
  
    @Override  
    protected Response 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 gsonRequest = new GsonRequest(url_json,YourClass.class,  
        new Response.Listener() {  
            @Override  
            public void onResponse(YourClass obj) {  
			//这里获得obj对应的json中的数据
            }  
        }, new Response.ErrorListener() {  
            @Override  
            public void onErrorResponse(VolleyError error) {  
                Log.e("TAG", error.getMessage(), error);  
            }  
        });




热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

6

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

104

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

12

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

102

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

5

2026.01.26

windows安全中心怎么关闭 windows安全中心怎么执行操作
windows安全中心怎么关闭 windows安全中心怎么执行操作

关闭Windows安全中心(Windows Defender)可通过系统设置暂时关闭,或使用组策略/注册表永久关闭。最简单的方法是:进入设置 > 隐私和安全性 > Windows安全中心 > 病毒和威胁防护 > 管理设置,将实时保护等选项关闭。

6

2026.01.26

2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】
2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】

铁路12306提供起售时间查询、起售提醒、购票预填、候补购票及误购限时免费退票五项服务,并强调官方渠道唯一性与信息安全。

105

2026.01.26

个人所得税税率表2026 个人所得税率最新税率表
个人所得税税率表2026 个人所得税率最新税率表

以工资薪金所得为例,应纳税额 = 应纳税所得额 × 税率 - 速算扣除数。应纳税所得额 = 月度收入 - 5000 元 - 专项扣除 - 专项附加扣除 - 依法确定的其他扣除。假设某员工月工资 10000 元,专项扣除 1000 元,专项附加扣除 2000 元,当月应纳税所得额为 10000 - 5000 - 1000 - 2000 = 2000 元,对应税率为 3%,速算扣除数为 0,则当月应纳税额为 2000×3% = 60 元。

29

2026.01.26

oppo云服务官网登录入口 oppo云服务登录手机版
oppo云服务官网登录入口 oppo云服务登录手机版

oppo云服务https://cloud.oppo.com/可以在云端安全存储您的照片、视频、联系人、便签等重要数据。当您的手机数据意外丢失或者需要更换手机时,可以随时将这些存储在云端的数据快速恢复到手机中。

82

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 9.7万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.2万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号