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
- * @author zimo2013
- * [url=home.php?mod=space&uid=189949]@See[/url] http://blog.csdn.net/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,该框架自己支持二级缓存,在BitmapLruCache封装一个软引用缓存
- mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(1024*1024*maxSize));
-
- LogUtil.i(TAG, "MyVolley初始化完成");
- }
-
- /**
- * 初始化Volley相关对象,在使用Volley前应该完成初始化
- *
- * @param context
- */
- public static void init(Context context) {
- if (instance == null) {
- instance = new MyVolley(context);
- } else {
- LogUtil.w(TAG, "已经初始化过,不须要再次调用init()");
- }
- }
-
- /**
- * 获得请求队列对象
- *
- * @return
- */
- public static RequestQueue getRequestQueue() {
- throwIfNotInit();
- return mRequestQueue;
- }
-
- /**
- * 获得ImageLoader对象
- *
- * @return
- */
- public static ImageLoader getImageLoader() {
- throwIfNotInit();
- return mImageLoader;
- }
-
- /**
- * 检查是否完成初始化
- */
- 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
- * @see http://blog.csdn.net/zimo2013
- */
- public class MyJsonRequest<T> extends JsonRequest<T> {
- private Gson gson;
- private Class<T> clazz;
-
- /**
- * 默认为GET请求方式
- * @param url
- * @param clazz 解析的class字节码
- * @param listener 请求成功监听器
- * @param errorListener 请求失败监听器
- */
- public MyJsonRequest(String url, Class<T> clazz, Listener<T> listener,
- ErrorListener errorListener) {
- this(Method.GET, url, null, clazz, listener, errorListener);
- }
-
- /**
- *
- * @param method 请求方法 Use {@link com.android.volley.Request.Method}.
- * @param url
- * @param requestBody 若是是POST请求,能够提交form表单字符串,好比 name=zhangsan&age=20
- * @param clazz 解析的class字节码
- * @param listener 请求成功监听器
- * @param errorListener 请求失败监听器
- */
- public MyJsonRequest(int method, String url, String requestBody, Class<T> clazz,
- Listener<T> listener, ErrorListener errorListener) {
- super(method, url, null, listener, errorListener);
-
- this.clazz = clazz;
- gson = new Gson();
- }
-
- @Override
- protected Response<T> parseNetworkResponse(NetworkResponse response) {
- try {
- String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
- return Response.success(gson.fromJson(json, clazz),
- 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
- }
|