vollery的使用小计

去年Google在IO大会上推出了vollery框架,适用于通信量不大但是通信频繁的情况,对普通的网络访问,json解析以及图片的加载都提供了很好的支持。


在真正的网络访问之前,首先需要做一些准备工作

		//创建一个请求调度队列
		RequestQueue rq = Volley.newRequestQueue(this);

RequestQueue的创建

    /**
     * 创建工作池并start
     */
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
        String userAgent = "volley/0";
        try {
            String packageName = context.getPackageName();
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException e) {
        }

        if (stack == null) {
        	/*
        	 * 在Android 2.3及以上版本,使用的是HttpURLConnection
        	 * 在Android 2.2及以下版本,使用的是HttpClient
        	 * reason:
        	 * 2.2之前HttpClient的bug较少,而HttpURLConnection的缺陷较多
        	 * 比如对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了
        	 * 2.2之后API简单,体积较小,因而非常适用于Android项目。
        	 * 压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。
        	 * 对于新的应用程序应该更加偏向于使用HttpURLConnection
        	 */
            if (Build.VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }
        if(null == network)
        	network = new BasicNetwork(stack);
        if(null == queue)
        	queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();
        return queue;
    }

普通的网络访问

		//创建一个请求调度队列
		RequestQueue rq = Volley.newRequestQueue(this);
		
		StringRequest request = new StringRequest(Method.GET, url, new Response.Listener<String>() {
			/**
			 * 访问成功返回数据
			 * @param response
			 */
			@Override
			public void onResponse(String response) {
				Log.i("response", response);
			}
		}, new Response.ErrorListener() {
			
			/**
			 * 网络访问失败处理及原因
			 */
			@Override
			public void onErrorResponse(VolleyError error) {
				if(error instanceof ServerError){//服务器错误
					Log.i("error", error.toString());
				}else if(error instanceof NoConnectionError){//无连接
					Log.i("error", error.toString());
				}else if(error instanceof TimeoutError){//超时
					Log.i("error", error.toString());
				}
			}
		});
		rq.add(request);
	

Json数据的访问

		RequestQueue rq = Volley.newRequestQueue(this);
		JsonObjectRequest request = new JsonObjectRequest(Method.GET, url, null,  
	            new Listener<JSONObject>() {
					@Override
					public void onResponse(JSONObject response) {
						Log.i("json", response.toString());
					}}, null);
		rq.add(request);
	

压轴:图片的访问

1.首先创建一个图片的缓存类,使用的是lruCache

package com.example.vollerytest;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Log;
import android.util.LruCache;

import com.android.volley.toolbox.ImageLoader.ImageCache;

public class BitmapCache implements ImageCache{
	
	@SuppressWarnings("unused")
	private static BitmapCache bitmapCache = null;
	private LruCache<String, Bitmap> cache = null;

	private void cacheInit(){
		int maxSize = (int) (Runtime.getRuntime().maxMemory() / 1024)/8;
		Log.i("memorySize", "use memory size is " + maxSize);
		cache = new LruCache<String, Bitmap>(maxSize){
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getRowBytes() * value.getHeight();
			}
		};
	}
	
	private BitmapCache(){
		cacheInit();
	}
	
	public static BitmapCache getInstance(){
		if(null == bitmapCache){
			bitmapCache = new BitmapCache();
		}
		return bitmapCache;
	}
	
	
	
	@SuppressLint("NewApi")
	@Override
	public Bitmap getBitmap(String url) {
		if(null != cache)
			return cache.get(url);
		else
		return null;
	}

	@Override
	public void putBitmap(String url, Bitmap bitmap) {
		if(!TextUtils.isEmpty(url) && null != bitmap && null != cache)
			cache.put(url, bitmap);
		else	
			throw new IllegalStateException();
	}	
	
}

2.创建一个图片加载和图片缓存的处理类

		//图片的加载和缓存处理类
		ImageLoader mImageLoader = new ImageLoader(rq, BitmapCache.getInstance()); 

3.图片获取

			//创建ImageView对象的监听,用于在图片成功获取或者图片获取失败时显示相应图片
			ImageListener listener = ImageLoader.getImageListener(ivArray[i], R.drawable.empty, R.drawable.empty);		
			//将图片的URL设置给ImageView
			mImageLoader.get(urls[i], listener);

小结

vollery对于普通的网络访问或json用起来还是比较舒服的,但是对于图片的请求,该框架只用了内存缓存,并未使用Disk的二级缓存,而且该框架没有对图片是否显示进行判断,比如说一个listview有200项,每一项都有一张图片,这时肯定需要下滑才能看见下面的图片,但是不管用户是否下滑listview,vollery都会将这200张图片全部下载完成,这样造成了一定程度上的运行时间,及流量的浪费。

相对于vollery,google所推出的另一套专门用于图片加载的框架,bitmapfun则有效的处理了这个问题,只有用户看到的图片才会去下载,也就是做了一个图片的懒加载,并且bitmapfun在缓存上做了硬盘和内存的双缓存。但是bitmapfun有一个非常头疼的问题。详情请看下面的链接

bitmapfun高效图片加载坑爹的地方

vollery中的disk缓存

package com.example.vollerytest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

public class DiskBitmapCache {
	public static final String TAG = "DiskBitmapCache";
	
	public static final String PATH = "/imageCache";
	
	public static final String CACHE_PATH = Environment.getExternalStorageDirectory() + PATH + File.separator;
	
	public static Bitmap getBitmapFromDiskCache(String url){
		
		if(TextUtils.isEmpty(url)){
			throw new NullPointerException();
		}
		
		String url_hashCode = hashKeyForDisk(url);
		
		File file = new File(Environment.getExternalStorageDirectory() + PATH + File.separator + url_hashCode);
		
		BitmapFactory.Options options = new BitmapFactory.Options();
		/*
		 * BitmapFactory.decodeFile并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,
		 * 这样就不会占用太多的内存,也就不会那么频繁的发生OOM了
		 * 但是这时候该方法返回的bitmap为null,在大图片加载的时候考虑
		 */
       /* options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file.getAbsolutePath(), options);//获取图片的宽高,计算以避免OOM
*/        
		if(null != file && file.exists())
			return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
		else
			return null;
		
	}
	
	/**
	 * 
	 */
	public static boolean saveBitmap2file(Bitmap bmp,String url){ 
		
		 // 判断SDcard状态
        if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
        {
            // 错误提示
            return false;
        }
                                                                                                                                                                                                                                                                                                        
        // 检查SDcard空间
        File SDCardRoot = Environment.getExternalStorageDirectory();
        if (SDCardRoot.getFreeSpace() < 10000)
        {
            // 弹出对话框提示用户空间不够
            Log.e("Utils", "存储空间不够");
            return false;
        }
        File bitmapFile = new File(CACHE_PATH);
        bitmapFile.mkdirs();// 创建文件夹
        CompressFormat format= Bitmap.CompressFormat.JPEG;  
        int quality = 100;  
        OutputStream stream = null;  
        try {  
             stream = new FileOutputStream(CACHE_PATH + hashKeyForDisk(url));  
        } catch (FileNotFoundException e) {  
        	e.printStackTrace();
        	Log.e(TAG, "FileNotFoundException");
        	return false;
        } 
        return bmp.compress(format, quality, stream);  
        }  
	
	
    /**
     * A hashing method that changes a string (like a URL) into a hash suitable for using as a
     * disk filename.
     * 将一个URL通过一个哈希算法转化成一个哈希值用来作为文件名
     */
    public static String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }
    
    private static String bytesToHexString(byte[] bytes) {
        // http://stackoverflow.com/questions/332079
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }
}

在ImageLoader的get方法中,当从内存中没有发现图片时,先去硬盘中查找,查找的key是图片URL生成的hash值,如果找到则转换成bitmap返回,如果为找到再去下载。

        //TODO:硬盘获取图片
        Bitmap diskBitmap = DiskBitmapCache.getBitmapFromDiskCache(requestUrl);
        if(diskBitmap != null){
        	ImageContainer container = new ImageContainer(diskBitmap, requestUrl, null, null);
        	imageListener.onResponse(container, true);
        	return container;
        }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值