/* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.image; import java.io.File; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.pm.PackageInfo; import android.graphics.Bitmap; import android.view.View; import android.widget.ImageView; import com.ab.cache.AbCacheHeaderParser; import com.ab.cache.AbCacheResponse; import com.ab.cache.AbCacheUtil; import com.ab.cache.AbDiskBaseCache; import com.ab.cache.AbDiskCache.Entry; import com.ab.cache.image.AbBitmapResponse; import com.ab.cache.image.AbImageBaseCache; import com.ab.global.AbAppConfig; import com.ab.task.AbTaskItem; import com.ab.task.AbTaskObjectListener; import com.ab.task.thread.AbTaskQueue; import com.ab.util.AbAppUtil; import com.ab.util.AbFileUtil; import com.ab.util.AbImageUtil; import com.ab.util.AbLogUtil; import com.ab.util.AbStrUtil; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbImageLoader.java * 描述:下载图片并显示的工具类. * * @author 还如一梦中 * @version v1.0 * @date:2011-12-10 上午10:10:53 */ public class AbImageLoader { /** 上下文. */ private Context context = null; /** 单例对象. */ private static AbImageLoader imageLoader = null; /** 缓存超时时间设置. */ private long cacheMaxAge; /** 请求队列. */ private List<AbTaskQueue> taskQueueList; /** 图片缓存. */ private AbImageBaseCache memCache; /** 磁盘缓存. */ private AbDiskBaseCache diskCache; /** * 构造图片下载器. * * @param context the context */ public AbImageLoader(Context context) { this.context = context; this.cacheMaxAge = AbAppConfig.DISK_CACHE_EXPIRES_TIME; this.taskQueueList = new ArrayList<AbTaskQueue>(); PackageInfo info = AbAppUtil.getPackageInfo(context); File cacheDir = null; if(!AbFileUtil.isCanUseSD()){ cacheDir = new File(context.getCacheDir(), info.packageName); }else{ cacheDir = new File(AbFileUtil.getCacheDownloadDir(context)); } this.diskCache = new AbDiskBaseCache(cacheDir); this.memCache = AbImageBaseCache.getInstance(); } /** * * 获得一个实例. * @param context * @return */ public static AbImageLoader getInstance(Context context) { if (imageLoader == null) { imageLoader = new AbImageLoader(context); } return imageLoader; } /** * * 显示这个图片. * @param imageView * @param url * @param desiredWidth * @param desiredHeight */ public void display(ImageView imageView,String url,int desiredWidth, int desiredHeight){ download(imageView,url,desiredWidth,desiredHeight,new OnImageListener() { @Override public void onSuccess(ImageView imageView, Bitmap bitmap) { imageView.setImageBitmap(bitmap); } @Override public void onLoading(ImageView imageView) { } @Override public void onError(ImageView imageView) { } @Override public void onEmpty(ImageView imageView) { } }); } /** * * 显示这个图片(按照原图尺寸). * ImageView使用android:scaleType="fitXY"属性仍旧可以充满 * @param imageView * @param url */ public void display(ImageView imageView,String url){ download(imageView,url,-1,-1,new OnImageListener() { @Override public void onSuccess(ImageView imageView, Bitmap bitmap) { imageView.setImageBitmap(bitmap); } @Override public void onLoading(ImageView imageView) { } @Override public void onError(ImageView imageView) { imageView.setVisibility(View.VISIBLE); imageView.setImageBitmap(null); } @Override public void onEmpty(ImageView imageView) { imageView.setVisibility(View.VISIBLE); imageView.setImageBitmap(null); } }); } /** * * 显示这个图片. * @param imageView * @param loadingView * @param url * @param desiredWidth * @param desiredHeight */ public void display(final ImageView imageView,final View loadingView,final String url,final int desiredWidth,final int desiredHeight){ download(imageView,url,desiredWidth,desiredHeight,new OnImageListener() { public void onSuccess(ImageView imageView, Bitmap bitmap) { imageView.setImageBitmap(bitmap); imageView.setVisibility(View.VISIBLE); loadingView.setVisibility(View.GONE); } @Override public void onLoading(ImageView imageView) { imageView.setVisibility(View.GONE); loadingView.setVisibility(View.VISIBLE); } @Override public void onError(ImageView imageView) { loadingView.setVisibility(View.GONE); imageView.setVisibility(View.VISIBLE); imageView.setImageBitmap(null); } @Override public void onEmpty(ImageView imageView) { imageView.setImageBitmap(null); loadingView.setVisibility(View.GONE); imageView.setVisibility(View.VISIBLE); } }); } /** * * 下载这个图片. * @param imageView * @param url * @param desiredWidth * @param desiredHeight */ public void download(final ImageView imageView,final String url,final int desiredWidth,final int desiredHeight,final OnImageListener onImageListener) { if(AbStrUtil.isEmpty(url)){ if(onImageListener!=null){ onImageListener.onEmpty(imageView); } return; } final String cacheKey = memCache.getCacheKey(url, desiredWidth, desiredHeight); //先看内存 Bitmap bitmap = memCache.getBitmap(cacheKey); AbLogUtil.i(AbImageLoader.class, "从LRUCache中获取到的图片"+cacheKey+":"+bitmap); if(bitmap != null){ if(onImageListener!=null){ onImageListener.onSuccess(imageView, bitmap); } }else{ if(onImageListener!=null){ onImageListener.onLoading(imageView); } if(imageView != null){ //设置标记,目的解决闪烁问题 imageView.setTag(url); } AbTaskItem item = new AbTaskItem(); item.setListener(new AbTaskObjectListener(){ @Override public <T> void update(T entity) { AbBitmapResponse response = (AbBitmapResponse)entity; if(response == null){ if(onImageListener!=null){ onImageListener.onError(imageView); } }else{ Bitmap bitmap = response.getBitmap(); //要判断这个imageView的url有变化,如果没有变化才set //有变化就取消,解决列表的重复利用View的问题 if(bitmap==null){ if(onImageListener!=null){ onImageListener.onEmpty(imageView); } }else if(imageView == null || url.equals(imageView.getTag())){ if(onImageListener!=null){ onImageListener.onSuccess(imageView, bitmap); } } AbLogUtil.d(AbImageLoader.class, "获取到图片:"+bitmap); } } @Override public AbBitmapResponse getObject() { return getBitmapResponse(url, desiredWidth, desiredHeight); } }); add2Queue(item); } } /** * * 下载这个图片. * @param url * @param desiredWidth * @param desiredHeight */ public void download(final String url,final int desiredWidth,final int desiredHeight,final OnImageListener2 onImageListener) { if(AbStrUtil.isEmpty(url)){ if(onImageListener!=null){ onImageListener.onEmpty(); } return; } final String cacheKey = memCache.getCacheKey(url, desiredWidth, desiredHeight); //先看内存 Bitmap bitmap = memCache.getBitmap(cacheKey); AbLogUtil.i(AbImageLoader.class, "从LRUCache中获取到的图片"+cacheKey+":"+bitmap); if(bitmap != null){ if(onImageListener!=null){ onImageListener.onSuccess(bitmap); } }else{ if(onImageListener!=null){ onImageListener.onLoading(); } AbTaskItem item = new AbTaskItem(); item.setListener(new AbTaskObjectListener(){ @Override public <T> void update(T entity) { AbBitmapResponse response = (AbBitmapResponse)entity; if(response == null){ if(onImageListener!=null){ onImageListener.onError(); } }else{ Bitmap bitmap = response.getBitmap(); //要判断这个imageView的url有变化,如果没有变化才set //有变化就取消,解决列表的重复利用View的问题 if(bitmap==null){ if(onImageListener!=null){ onImageListener.onEmpty(); } }else { if(onImageListener!=null){ onImageListener.onSuccess(bitmap); } } AbLogUtil.d(AbImageLoader.class, "获取到图片:"+bitmap); } } @Override public AbBitmapResponse getObject() { try { return getBitmapResponse(url, desiredWidth, desiredHeight); } catch (Exception e) { e.printStackTrace(); } return null; } }); add2Queue(item); } } /** * * 获取AbBitmapResponse. * @param url * @param desiredWidth * @param desiredHeight * @return */ public AbBitmapResponse getBitmapResponse(String url,int desiredWidth,int desiredHeight){ AbBitmapResponse bitmapResponse = null; try { final String cacheKey = memCache.getCacheKey(url, desiredWidth, desiredHeight); Bitmap bitmap = null; //看磁盘 Entry entry = diskCache.get(cacheKey); if(entry == null || entry.isExpired()){ if(entry == null){ AbLogUtil.i(AbImageLoader.class, "磁盘中没有这个图片"); }else{ if(entry.isExpired()){ AbLogUtil.i(AbImageLoader.class, "磁盘中图片已经过期"); } } AbCacheResponse response = AbCacheUtil.getCacheResponse(url); if(response!=null){ bitmap = AbImageUtil.getBitmap(response.data, desiredWidth, desiredHeight); if(bitmap!=null){ memCache.putBitmap(cacheKey, bitmap); AbLogUtil.i(AbImageLoader.class, "图片缓存成功"); diskCache.put(cacheKey, AbCacheHeaderParser.parseCacheHeaders(response,cacheMaxAge)); } } }else{ //磁盘中有 byte [] bitmapData = entry.data; bitmap = AbImageUtil.getBitmap(bitmapData, desiredWidth, desiredHeight); memCache.putBitmap(cacheKey, bitmap); } bitmapResponse = new AbBitmapResponse(url); bitmapResponse.setBitmap(bitmap); } catch (Exception e) { e.printStackTrace(); } return bitmapResponse; } /** * * 设置缓存的最大时间. * @return */ public long getCacheMaxAge() { return cacheMaxAge; } /** * * 获取缓存的最大时间. * @param cacheMaxAge */ public void setCacheMaxAge(long cacheMaxAge) { this.cacheMaxAge = cacheMaxAge; } /** * 监听器 */ public interface OnImageListener { /** * On Empty. * @param imageView */ public void onEmpty(ImageView imageView); /** * On Loading. * @param imageView */ public void onLoading(ImageView imageView); /** * On Error. * @param imageView */ public void onError(ImageView imageView); /** * * On response. * @param imageView * @param bitmap */ public void onSuccess(ImageView imageView,Bitmap bitmap); } /** * 监听器 */ public interface OnImageListener2 { /** * On Empty. * @param imageView */ public void onEmpty(); /** * On Loading. * @param imageView */ public void onLoading(); /** * On Error. * @param imageView */ public void onError(); /** * * On response. * @param imageView * @param bitmap */ public void onSuccess(Bitmap bitmap); } /** * * 增加到最少的队列中. * @param item */ private void add2Queue(AbTaskItem item){ int minQueueIndex = 0; if(taskQueueList.size() == 0){ AbTaskQueue queue = AbTaskQueue.newInstance(); taskQueueList.add(queue); queue.execute(item); }else{ int minSize = 0; for(int i=0;i<taskQueueList.size();i++){ AbTaskQueue queue = taskQueueList.get(i); int size = queue.getTaskItemListSize(); if(i==0){ minSize = size; minQueueIndex = i; }else{ if(size < minSize){ minSize = size; minQueueIndex = i; } } } if(taskQueueList.size() <5 && minSize > 2){ AbTaskQueue queue = AbTaskQueue.newInstance(); taskQueueList.add(queue); queue.execute(item); }else{ AbTaskQueue minQueue = taskQueueList.get(minQueueIndex); minQueue.execute(item); } } for(int i=0;i<taskQueueList.size();i++){ AbTaskQueue queue = taskQueueList.get(i); int size = queue.getTaskItemListSize(); AbLogUtil.i(AbImageLoader.class, "线程队列["+i+"]的任务数:"+size); } } /** * * 释放资源. */ public void cancelAll(){ for(int i=0;i<taskQueueList.size();i++){ AbTaskQueue queue = taskQueueList.get(i); queue.cancel(true); } taskQueueList.clear(); } public AbImageBaseCache getMemCache() { return memCache; } public void setMemCache(AbImageBaseCache memCache) { this.memCache = memCache; } public AbDiskBaseCache getDiskCache() { return diskCache; } public void setDiskCache(AbDiskBaseCache diskCache) { this.diskCache = diskCache; } }