Android_开源框架_Volley实例
由于博主的水平有限,如有误,请您帮助指正,共同学习,共同进步!
供初学者更好的理解和管理Volley!
1.自定义相关类
在Android_开源框架_Volley(Google IO 2013)源代码及内部实现过程分析一文中,简单概述了Volley框架内部实现过程。如想理解彻底应该熟悉android多线程通信机制(Android_Thread多线程_Handler,Message,Looper,MessageQueue多线程和特殊UI更新一文) ,JDK1.5提供的java.util.concurrent相关并发库和http访问网络(Android_HttpURLConnection_Get和Post请求[该框架使用]/Android_HttpClient_get请求post表单提交上传一文)及图片缓存(Android_图片的三级缓存一文)相关知识
https://android.googlesource.com/platform/frameworks/volley
(1).封装MyVolley类
在使用Volley之前,应该先进行初始化(可以自定义Application或者在SplashActivity中完成初始化),仅对外提供RequestQueue(添加request)和ImageLoader(下载图片)get方法!
/** * MyVolley.java * @see http://blog.csdn.net/zimo2013 * @author zimo2013 * */ public class MyVolley { private static final String TAG = "MyVolley"; private static MyVolley instance; private static RequestQueue mRequestQueue; private static ImageLoader mImageLoader; private final static int RATE = 8; // 默认分配最大空间的几分之一 private MyVolley(Context context) { mRequestQueue = Volley.newRequestQueue(context); // 确定在LruCache中,分配缓存空间大小,默认程序分配最大空间的 1/8 ActivityManager manager = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); int maxSize = manager.getMemoryClass() / RATE; // 比如 64M/8,单位为M // BitmapLruCache自定义缓存class,android本身支持二级缓存,在BitmapLruCache封装一个软引用缓存 mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache( 1024 * 1024 * maxSize)); Log.i(TAG, "MyVolley初始化完成"); } /** * 初始化Volley相关对象,在使用Volley前应该完成初始化 * * @param context */ public static void init(Context context) { if (instance == null) { instance = new MyVolley(context); } } /** * 得到请求队列对象 * * @return */ private static RequestQueue getRequestQueue() { throwIfNotInit(); return mRequestQueue; } /** * 得到ImageLoader对象 * * @return */ public static ImageLoader getImageLoader() { throwIfNotInit(); return mImageLoader; } public static void addRequest(Request<?> request) { getRequestQueue().add(request); } public static void getImage(String requestUrl, ImageView imageView) { getImage(requestUrl, imageView, 0, 0); } public static void getImage(String requestUrl, ImageView imageView, int defaultImageResId, int errorImageResId) { getImage(requestUrl, imageView, defaultImageResId, errorImageResId, 0, 0); } public static void getImage(String requestUrl, ImageView imageView, int defaultImageResId, int errorImageResId, int maxWidth, int maxHeight) { imageView.setTag(requestUrl); getImageLoader().get(requestUrl, ImageListenerFactory.getImageListener( imageView, defaultImageResId, errorImageResId), maxWidth, maxHeight); } /** * 检查是否完成初始化 */ private static void throwIfNotInit() { if (instance == null) {// 尚未初始化 throw new IllegalStateException("MyVolley尚未初始化,在使用前应该执行init()"); } } }(2).图片的三级缓存相关类
/** * LruCache缓存管理类,该类实现了ImageCache接口,并实现了LruCache * 一旦bitmap对象从LruCache中被挤出,将会被放置在BitmapSoftRefCache中,再配合该框架本身支持的硬盘缓存,可以完成图片三级缓存 * * BitmapLruCache.java * @author zimo2013 * @see http://blog.csdn.net/zimo2013 * */ public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache { private static final String TAG = "BitmapLruCache"; private BitmapSoftRefCache softRefCache; public BitmapLruCache(int maxSize) { super(maxSize); softRefCache = new BitmapSoftRefCache(); } @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight(); } @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { if (evicted) { LogUtil.i(TAG, "空间已满,缓存图片被挤出:" + key); // 将被挤出的bitmap对象,添加至软引用BitmapSoftRefCache softRefCache.putBitmap(key, oldValue); } } /** * 得到缓存对象 */ @Override public Bitmap getBitmap(String url) { Bitmap bitmap = get(url); // 如果bitmap为null,尝试从软引用缓存中查找 if (bitmap == null) { bitmap = softRefCache.getBitmap(url); } else { LogUtil.i(TAG, "LruCache命中:" + url); } return bitmap; } /** * 添加缓存对象 */ @Override public void putBitmap(String url, Bitmap bitmap) { put(url, bitmap); } }/** * 软引用缓存管理类 * * BitmapSoftRefCache.java * @author zimo2013 * @see http://blog.csdn.net/zimo2013 * */ public class BitmapSoftRefCache implements ImageCache{ private static final String TAG = "BitmapSoftRefCache"; private LinkedHashMap<String, SoftReference<Bitmap>> map; public BitmapSoftRefCache() { map = new LinkedHashMap<String, SoftReference<Bitmap>>(); } /** * 从软引用集合中得到Bitmap对象 */ @Override public Bitmap getBitmap(String url) { Bitmap bitmap = null; SoftReference<Bitmap> softRef = map.get(url); if(softRef != null){ bitmap = softRef.get(); if(bitmap == null){ map.remove(url); //从map中移除 LogUtil.w(TAG, url+"对象已经被GC回收"); }else{ LogUtil.i(TAG, "命中"+url); } } return bitmap; } /** * 从软引用集合中添加bitmap对象 */ @Override public void putBitmap(String url, Bitmap bitmap) { SoftReference<Bitmap> softRef = new SoftReference<Bitmap>(bitmap); map.put(url, softRef); } }
(3).图片错位
关于使用该框架造成图片错位问题,App使用了ImageLoader下载图片,当ListView滚动很快时,还是会发生错位!记得听别人提起过,使用该框架可以避免图片错位,但是结果还是会发生错位,查看源码并没有找到相关避免错位的措施,不知道是不是自己的使用方法不对,如您知晓,麻烦告知博主一下~
这里通过覆写ImageListener方法,通过ImageView为其指定Tag标签,防止图片错位,即比对下载完图片的ImageUrl和当前该ImageView的Tag是否相等~
public class ImageListenerFactory{ public static ImageListener getImageListener(final ImageView view, final int defaultImageResId, final int errorImageResId) { return new ImageListener() { @Override public void onErrorResponse(VolleyError error) { if (errorImageResId != 0) { view.setImageResource(errorImageResId); } } @Override public void onResponse(ImageContainer response, boolean isImmediate) { if (response.getBitmap() != null) { if(view.getTag().toString() == response.getRequestUrl()){ view.setImageBitmap(response.getBitmap()); }else{ LogUtil.i(TAG, "图片错位"); } } else if (defaultImageResId != 0) { view.setImageResource(defaultImageResId); } } }; } }
2.网络请求Request
(1).StringRequest
public void testStringRequest(){ String url = "http://www.baidu.com"; //如果出现乱码,应该修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 编码 MyVolley.getRequestQueue().add(new StringRequest(url, new Response.Listener<String>() { @Override public void onResponse(String response) { System.out.println("response:"+response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } })); }(2).JsonObjectRequest
public void testJsonObjectRequest(){ String url = "http://api.mobile.meituan.com/group/v1/deal/new-cate-list/android/4.1?cityId=1"; //如果出现乱码,应该修改StringRequest的parseNetworkResponse()方法,指定byte[]-->String 编码 MyVolley.getRequestQueue().add( new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { //该JSONObject为android系统提供的,如果希望得到一个已经解析完的对象,可以继承JsonRequest //根据response,解析数据 try { System.out.println(response.get("stid")); } catch (JSONException e) { e.printStackTrace(); } } },new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { System.out.println(error); } }) ); }(3).自定义Request(Json解析)
/** * MyJsonRequest.java * * @author zimo2013 */ public class MyJsonListRequest<T> extends JsonRequest<T> { private Gson gson; private Class<T> clazz; private String mKey; /** * GET请求方式,直接将json字符串解析为 对应的clazz对象 * * @param url * 请求url * @param clazz * 解析的class字节码 * @param listener * 请求成功监听器 * @param errorListener * 请求失败监听器 */ public MyJsonListRequest(String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { this(url, null, clazz, listener, errorListener); } /** * GET请求方式,将json中的key对应的value解析为 对应的clazz对象 * * @param url * 请求url * @param key * 取得指定的key,<b>NOTE:</b>只支持 root-key,所有子key均错误 * @param clazz * 解析的class字节码 * @param listener * 请求成功监听器 * @param errorListener * 请求失败监听器 */ public MyJsonListRequest(String url, String key, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { this(Method.GET, url, null, key, clazz, listener, errorListener); } /** * * @param method * 请求方法 Use {@link com.android.volley.Request.Method}. * @param url * @param requestBody * 如果是POST请求,可以提交form表单字符串,比如 name=zhangsan&age=20 * @param key * 取得指定的key,<b>NOTE:</b>只支持 root-key,所有子key均错误 * @param clazz * 解析的class字节码 * @param listener * 请求成功监听器 * @param errorListener * 请求失败监听器 */ public MyJsonListRequest(int method, String url, String requestBody, String key, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { super(method, url, null, listener, errorListener); this.clazz = clazz; mKey = key; gson = new Gson(); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); T t = null; if(mKey == null){ t = gson.fromJson(json, clazz); }else{ JsonObject jsonObject = gson.fromJson(json, JsonObject.class); t = gson.fromJson(jsonObject.get(mKey), clazz); } return Response.success(t, HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } }public void testCustomRequest(){ String urlString = "http://192.168.117.120:8080/news/json.html"; MyJsonRequest<NewsInfo> request = new MyJsonRequest<NewsInfo>(urlString, NewsInfo.class, new Listener<NewsInfo>() { @Override public void onResponse(NewsInfo response) { System.out.println(response.getClass()); System.out.println(response); } }, null); MyVolley.getRequestQueue().add(request); }(4).POST表单提交
public void testRequestByPost(){ String urlString = "http://192.168.43.240:8080/news/servlet/Post"; StringRequest request = new StringRequest(Method.POST, urlString, new Listener<String>() { @Override public void onResponse(String response) { } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }){ //覆写getBody()方法提交表单数据 @Override public byte[] getBody() { return "name=zhangsan&age=15".getBytes(); } }; MyVolley.getRequestQueue().add(request); }(5).ImageLoader异步加载图片(防错位)
public void testImageLoader(){ MyVolley.getImageLoader().get(imgUrl, //ImageListenerFactory为自定义类,封装后即可获取图片资源,完成UI更新 ImageListenerFactory.getImageListener(//参考ImageLoader.getImageListener() imageView, // ImageView对象 R.drawable.ic_launcher, // 默认Image,如果不设应置为0 R.drawable.ic_launcher)); // 错误Image,如果不设应置为0 }
相关推荐
本教程将通过一个简单的示例来解释如何利用Volley框架进行网络编程,实现Android客户端与服务器之间的数据交换。 首先,我们要了解Volley的核心组件。Volley包含以下关键部分: 1. RequestQueue:这是Volley的核心...
这可能包括Android SDK中的关键类和方法解析,如Activity、Intent、BroadcastReceiver、Service、ContentProvider等核心组件的源码阅读,以及Android框架层的一些重要库如AndroidX、Volley、Retrofit、OkHttp等的...
这个压缩包"Android_上百实例源码分析以及开源分析_集合打包5"显然包含了大量关于Android编程的实例源码和开源项目的分析资料,旨在帮助开发者拓宽视野,增强实战经验。下面我们将详细探讨其中可能涵盖的知识点。 1...
总结,Android中解析JSON数据涉及的关键知识点包括JSON的基本结构、Gson库的使用、JSONObject和JSONArray的操作、Volley库的网络请求以及Retrofit框架的使用。这些工具和技术使得Android开发者能够高效地处理服务器...
本资源"Android+上百实例源码分析以及开源分析+集合打包9"提供了一系列的实战案例和源代码,帮助开发者深入理解Android开发的核心概念,并提升实际操作技能。下面我们将逐一解析这些实例及其涉及的关键知识点。 1. ...
开源框架在IT行业中扮演着至关重要的角色,尤其是在安卓开发领域。开源框架的广泛使用促进了技术创新,...这个“【06】开源框架”压缩包很可能包含了一些实例、教程或者项目源码,是学习和理解安卓开源框架的好材料。
Android提供了多种异步处理框架,其中一个被广泛使用的开源框架是“android-async-http”,它是一个轻量级、高性能的网络库,非常适合进行HTTP请求。 **Android异步操作的重要性** 在Android系统中,主线程负责处理...
本资源包包含了多个开源框架的应用实例,是安卓开发者深入理解和学习的宝贵资料。 首先,我们来看"Libraries for developersV3.39.apk"。这个应用可能是一个集成各种开发库的演示平台,它可能涵盖了网络请求库如...
Volley是一个由Google开发的Android网络库,设计用于高效地处理网络请求,特别是对于移动设备。它的主要目标是简化网络编程,提供一个低延迟、高响应的网络请求库。本项目是对Volley进行了二次封装,增加了更多的...
10. **依赖注入**:Dagger2或Hilt等依赖注入框架的运用,让代码更模块化,易于维护。 11. **测试与调试**:源码中可能包含单元测试和UI测试,让开发者学习如何编写和执行测试用例,提升代码质量。 通过以上分析,...
《Android核心技术与实例详解》是一本专为Android开发者设计的深度学习资料,涵盖了Android平台的基础概念、核心组件以及实际开发中的各种技术问题。通过阅读这本书,开发者可以深入了解Android系统的架构和工作原理...
"安卓巴士总结了近百个Android优秀开源项.zip"这个压缩包文件,显然是一个汇聚了众多高质量Android开源项目的集合,对于Android开发者来说,这是一个不可多得的学习资源库。 首先,我们要理解什么是开源项目。开源...
这个压缩包文件“Android应用源码-Android安卓设计实例源代码43个合集.zip”包含了一组丰富的Android应用程序源代码实例,对于Android开发者来说,这是一份极具价值的学习资源。这些实例涵盖了Android开发中的各种...
Android作为一个开源的移动操作系统,广泛应用于智能手机和平板电脑。而Web Service则是一种基于HTTP协议的远程调用技术,能够实现不同平台间的数据交换。本实例将深入探讨如何在Android应用中与Web Service进行通信...
总之,开源中国社区的Android源码是一个全面的Android应用开发实例,涵盖了用户交互、数据处理、网络通信、性能优化等多个方面,对于开发者来说,深入研究这个源码,无疑能提升对Android开发的理解和技能。...
在Volley中,`MultipartRequest`并不是内置的类,但我们可以自己实现或者使用开源的扩展。例如,`TestMultipartRequest-master`这个项目可能提供了这样的实现。通常,`MultipartRequest`需要继承自`Request`,并...
文档“安卓巴士总结了近百个Android优秀开源项.doc”是一个包含丰富Android开发资源的压缩包,其中列举了许多高质量的Android开源项目。这些项目通常由全球的开发者社区维护,旨在提供学习、参考和实际开发中的解决...
【Android视频软件开源代码】是针对移动设备,特别是Android手机的开源项目,它允许开发者深入理解视频播放软件的实现机制,并能在此基础上进行二次开发或自定义功能。这个开源项目为学习Android应用开发,尤其是...
Android开发是全球范围内广泛使用的移动应用开发平台,尤其在中国,由于其开源、灵活的特性,吸引了大量的开发者参与其中。本教程是针对中文开发者设计的最新版指南,旨在帮助初学者和有经验的开发者进一步提升在...