获取图像Demo(内存缓存>磁盘缓存>网络)

来源:互联网 发布:怎么备份手机应用数据 编辑:程序博客网 时间:2024/06/07 13:36
public class ImageLoader {//下载任务执行完毕后发送的message的whatpublic static final int LOAD_FINISH = 101;public static final int NEW_TASK = 102;//线程池中线程的数量//(这个数量应该与设备cpu的核数相同)public static int Thread_Count;public static Context c;//上下文//内存缓存public static LruCache<String, Bitmap> MemCache;//(双向)任务队列//未来可以根据需求选择是FIFO还是LIFOpublic static LinkedBlockingDeque<Runnable> taskQueue;//线程池public static ExecutorService exec;//从任务队列中取下载任务的handlerpublic static Handler pollHandler;//任务下载完毕后,用来刷新ListView条目显示下载图片的Handlerpublic static Handler uiHandler;//"养活"pollHandlerpublic static Thread pollThread;//磁盘缓存public static DiskLruCache DiskCache;//标示的作用,用来确保ImageLoader只要进行一次//初始化操作即可public static boolean isFirstTime = true;/** * 初始化ImageLoader所有属性的值 * @param context */public static void init(Context context){if(!isFirstTime){return;}//c属性赋值c = context;//获取cpu的核数为Thread_Count赋值Thread_Count = getNumberOfCores();//初始化内存缓存MemCache = new LruCache<String, Bitmap>((int) (Runtime.getRuntime().maxMemory()/8)){@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getHeight()*value.getRowBytes();}};//初始化磁盘缓存try {DiskCache = DiskLruCache.open(directory(), appVersion(), 1, 1024*1024*10);} catch (IOException e1) {e1.printStackTrace();}//初始化任务队列taskQueue = new LinkedBlockingDeque<Runnable>();exec = Executors.newFixedThreadPool(Thread_Count);//pollHandler, uiHandleruiHandler = new Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {//利用线程池中执行完毕的内容,来刷新ListViewif(msg.what==LOAD_FINISH){//msg.obj到底放什么?//msg.obj放什么能解决ListView加载“动画”效果ValueObject vo = (ValueObject) msg.obj;ImageView iv = vo.iv;String url = vo.url;Bitmap bitmap = vo.bitmap;if(iv.getTag().toString().equals(url)){iv.setImageBitmap(bitmap);}}else{super.handleMessage(msg);}}};pollThread = new Thread(){@Overridepublic void run() {Looper.prepare();pollHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {if(msg.what==NEW_TASK){//现在任务队列中被放入了新“下载任务”//去队列中取任务try {Runnable task = taskQueue.takeFirst();//将取出的任务放到线程池中执行exec.execute(task);} catch (InterruptedException e) {e.printStackTrace();}}else{super.handleMessage(msg);}}};Looper.loop();}};pollThread.start();isFirstTime = false;}private static int appVersion() {try {PackageInfo info = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);return info.versionCode;} catch (NameNotFoundException e) {e.printStackTrace();}return 1;}private static File directory() {//有些环境在执行getExternalCacheDir获取//外部的缓存路径的时候可能会报空指针异常//所以这里采用了内部缓存路径String path = c.getCacheDir().getPath();return new File(path,"imageloadercache");}/** * 获取url指向的图像,放到iv中显示 * @param url 图像路径 * @param iv 显示图像的ImageView */public static void loadImage(final String url,final ImageView iv){if(isFirstTime){throw new RuntimeException("ImageLoader未做初始化");}//先判断,url所指向的图像是否在缓存中有保存//url转为MD5格式的字符串final String md5Url = getMD5(url);//设置TAG,到时候要与vo中的URL进行比对!iv.setTag(md5Url);Bitmap bitmap = MemCache.get(md5Url);if(bitmap!=null){Log.d("TAG","图像是从内存缓存中加载的");iv.setImageBitmap(bitmap);return;}try {//从磁盘缓存中试图取出url所对应的图片Snapshot snap = DiskCache.get(md5Url);if(snap!=null){Log.d("TAG","图像是从磁盘缓存中获取的");InputStream in = snap.getInputStream(0);bitmap = BitmapFactory.decodeStream(in);//将从磁盘缓存中获得的图片放到内存缓存存储一份MemCache.put(md5Url, bitmap);iv.setImageBitmap(bitmap);return;}} catch (IOException e1) {e1.printStackTrace();}//从网络中下载taskQueue.add(new Runnable() {@Overridepublic void run() {//下载任务//发起网络连接,获得图像资源try{URL u = new URL(url);HttpURLConnection connection = (HttpURLConnection) u.openConnection();connection.setRequestMethod("GET");connection.setDoInput(true);connection.connect();InputStream is = connection.getInputStream();//要对图像进行压缩Bitmap bitmap = compress(is,iv);is.close();//将压缩后的图像放到内存缓存中存储MemCache.put(md5Url, bitmap);//将压缩后的图像放到磁盘缓存中存储Editor editor = DiskCache.edit(md5Url);OutputStream os = editor.newOutputStream(0);bitmap.compress(CompressFormat.JPEG, 100, os);editor.commit();//写日志(可选操作)DiskCache.flush();ValueObject vo = new ValueObject(iv, md5Url, bitmap);Message.obtain(uiHandler, LOAD_FINISH, vo).sendToTarget();}catch(Exception e){e.printStackTrace();}}});Message.obtain(pollHandler, NEW_TASK).sendToTarget();}/** * 根据要显示的ImageView的大小对图像进行压缩 * @param is 图像源 * @param iv 未来要显示图像的ImageView * @return 压缩过后的图像 */protected static Bitmap compress(InputStream is, ImageView iv) {Bitmap bitmap = null;try{//1)先获得原始图像(图像源)的尺寸大小//借助Optioins来获取图像的大小//is----------byte[]ByteArrayOutputStream out = new ByteArrayOutputStream();byte[] buff = new byte[4096];int len = -1;while((len=is.read(buff))!=-1){out.write(buff, 0, len);}Options opts = new Options();opts.inJustDecodeBounds = true;//opts一旦设定了inJustDecodeBounds = true//BitmapFactory是不会返回bitmap对象,只会nullBitmapFactory.decodeByteArray(out.toByteArray(),0, out.toByteArray().length, opts);int width = opts.outWidth;//图像的宽度(像素数)int height = opts.outHeight;//图像高度(像素数)//2)获取希望的宽度/高度int targetWidth  = iv.getWidth();//ImageView的宽度int targetHeight = iv.getHeight();//Imageview的高度//如果取ImageView宽度/高度取不到if(targetHeight==0||targetWidth==0){//可以手动指定值(80dp,100dp)//以当前设备屏幕的宽度/和高度来作为targetWiddth/targetHeighttargetWidth = c.getResources().      getDisplayMetrics().      widthPixels;targetHeight = c.getResources().      getDisplayMetrics().      heightPixels;}//3)计算压缩比int sampleSize = 1;if(width*1.0/targetWidth>1||height*1.0/targetHeight>1){sampleSize = (int) Math.ceil(Math.max(width*1.0/targetWidth,  height*1.0/targetHeight));}//4)压缩图像opts.inSampleSize = sampleSize;opts.inJustDecodeBounds = false;bitmap = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.toByteArray().length,opts);out.close();}catch(Exception e){e.printStackTrace();}return bitmap;}private static String getMD5(String url) {String result="";try {MessageDigest md = MessageDigest.getInstance("md5");md.update(url.getBytes());byte[] bytes = md.digest();StringBuilder sb = new StringBuilder();for(byte b:bytes){String str = Integer.toHexString(b & 0xFF);if(str.length()==1){sb.append("0");}sb.append(str);}result = sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return result;}private static int getNumberOfCores() {File file = new File("/sys/devices/system/cpu/");File[] files = file.listFiles(new FilenameFilter() {@Overridepublic boolean accept(File dir, String filename) {if(filename.matches("cpu[0-9]")){return true;}else{return false;}}});if(files.length>0){return files.length;}else{return 1;}}private static class ValueObject{ImageView iv;//发起下载任务的那个ImageViewString url;//下载任务中要下载的那个地址Bitmap bitmap;//url所对应的图片public ValueObject(ImageView iv, String url, Bitmap bitmap) {super();this.iv = iv;this.url = url;this.bitmap = bitmap;}}}


需要导入 DiskLruCache类支持。

点击打开链接


大概思想





0 0
原创粉丝点击