1.三级缓存的代码。
public class PhotoWallAdapter extends BaseAdapter implements OnScrollListener {private List<Costume> listCostumes;private Activity mActivity;private String path;/** * 记录所有正在下载或等待下载的任务。 */private Set<BitmapWorkerTask> taskCollection;/** * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。 */private LruCache<String, Bitmap> mMemoryCache;/** * GridView的实例 */private GridView mPhotoWall;/** * 第一张可见图片的下标 */private int mFirstVisibleItem;/** * 一屏有多少张图片可见 */private int mVisibleItemCount;/** * 记录是否刚打开程序,用于解决进入程序不滚动屏幕,不会下载图片的问题。 */private boolean isFirstEnter = true;@SuppressLint("NewApi")public PhotoWallAdapter(Activity mActivity,List<Costume> listCostume,String path,GridView photoWall) {this.mActivity=mActivity;this.mPhotoWall = photoWall;this.listCostumes=listCostume;this.path=path;taskCollection = new HashSet<BitmapWorkerTask>();// 获取应用程序最大可用内存int maxMemory = (int) Runtime.getRuntime().maxMemory();int cacheSize = maxMemory / 8;// 设置图片缓存大小为程序最大可用内存的1/8mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {@SuppressLint("NewApi")@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getByteCount();}};this.mPhotoWall.setOnScrollListener(this);}public void initData(List<Costume> listCostume){this.listCostumes=listCostume;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder=null;if(convertView==null){ viewHolder=new ViewHolder(); convertView=LayoutInflater.from(mActivity).inflate(R.layout.item,null); viewHolder.detail=(TextView) convertView.findViewById(R.id.grid_tv_detail); viewHolder.dollar=(TextView) convertView.findViewById(R.id.grid_tv_dollar); viewHolder.iv=(ImageView) convertView.findViewById(R.id.iv_gridId); convertView.setTag(viewHolder);}else{ viewHolder=(ViewHolder) convertView.getTag();}viewHolder.detail.setText("【超值惠】"+listCostumes.get(position).getDetail());viewHolder.dollar.setText("$"+listCostumes.get(position).getPrice());String imagePath=listCostumes.get(position).getImageUrl();viewHolder.iv.setImageResource(R.drawable.ic_launcher);// 给ImageView设置一个Tag,保证异步加载图片时不会乱序viewHolder.iv.setTag(imagePath);setImageView(imagePath,viewHolder.iv);return convertView;}/** * 给ImageView设置图片。首先从LruCache中取出图片的缓存,设置到ImageView上。如果LruCache中没有该图片的缓存, * 就给ImageView设置一张默认图片。 * * @param imageUrl * 图片的URL地址,用于作为LruCache的键。 * @param imageView * 用于显示图片的控件。 */private void setImageView(String imageUrl, ImageView imageView) {Bitmap bitmapCache = getBitmapFromMemoryCache(imageUrl);if (bitmapCache != null) {imageView.setImageBitmap(bitmapCache);}else {imageView.setImageResource(R.drawable.empty_photo);}}/** * 将一张图片存储到LruCache中。 * * @param key * LruCache的键,这里传入图片的URL地址。 * @param bitmap * LruCache的键,这里传入从网络上下载的Bitmap对象。 */public void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (getBitmapFromMemoryCache(key) == null) {mMemoryCache.put(key, bitmap);}}/** * 从LruCache中获取一张图片,如果不存在就返回null。 * * @param key * LruCache的键,这里传入图片的URL地址。 * @return 对应传入键的Bitmap对象,或者null。 */public Bitmap getBitmapFromMemoryCache(String key) {return mMemoryCache.get(key);}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// 仅当GridView静止时才去下载图片,GridView滑动时取消所有正在下载的任务if (scrollState == SCROLL_STATE_IDLE) {loadBitmaps(mFirstVisibleItem, mVisibleItemCount);} else {cancelAllTasks();}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,int totalItemCount) {mFirstVisibleItem = firstVisibleItem;mVisibleItemCount = visibleItemCount;// 下载的任务应该由onScrollStateChanged里调用,但首次进入程序时onScrollStateChanged并不会调用,// 因此在这里为首次进入程序开启下载任务。if (isFirstEnter && visibleItemCount > 0) {loadBitmaps(firstVisibleItem, visibleItemCount);isFirstEnter = false;}}/** * 加载Bitmap对象。此方法会在LruCache中检查所有屏幕中可见的ImageView的Bitmap对象, * 如果发现任何一个ImageView的Bitmap对象不在缓存中,就会开启异步线程去下载图片。 * * @param firstVisibleItem * 第一个可见的ImageView的下标 * @param visibleItemCount * 屏幕中总共可见的元素数 */private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {try {for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {String imageUrl =listCostumes.get(i).getImageUrl();Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);if (bitmap == null) {String imageName = "";if (imageUrl != null) {imageName = Util.getInstance().getImageName(imageUrl);} if(imageView != null && imageUrl.equals(imageView.getTag())) {Bitmap bitmapfile = getBitmapFromFile(mActivity, imageName, path);if (bitmapfile != null) {imageView.setImageBitmap(bitmapfile);}else{ BitmapWorkerTask task = new BitmapWorkerTask(); taskCollection.add(task); task.execute(imageUrl);} }} else {if (imageView != null && bitmap != null) {imageView.setImageBitmap(bitmap);}}}} catch (Exception e) {e.printStackTrace();}}/** * 取消所有正在下载或等待下载的任务。 */public void cancelAllTasks() {if (taskCollection != null) {for (BitmapWorkerTask task : taskCollection) {task.cancel(false);}}}/** * 异步下载图片的任务。 * * @author guolin */class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {/** * 图片的URL地址 */private String imageUrl;@Overrideprotected Bitmap doInBackground(String... params) {imageUrl = params[0];// 在后台开始下载图片Bitmap bitmap = downloadBitmap(params[0]);if (bitmap != null) {String imageName = Util.getInstance().getImageName(imageUrl); if(!setBitmapToFile(path,mActivity,imageName,bitmap)){removeBitmapFromFile(imageName, mActivity, imageName);}// 图片下载完成后缓存到LrcCache中addBitmapToMemoryCache(params[0], bitmap);}return bitmap;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);// 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);if (imageView != null && bitmap != null) {imageView.setImageBitmap(bitmap);}taskCollection.remove(this);}/** * 建立HTTP请求,并获取Bitmap对象。 * * @param imageUrl * 图片的URL地址 * @return 解析后的Bitmap对象 */private Bitmap downloadBitmap(String imageUrl) {Bitmap bitmap = null;HttpURLConnection con = null;try {URL c_url = new URL(imageUrl);InputStream bitmap_data = c_url.openStream();bitmap = BitmapFactory.decodeStream(bitmap_data);} catch (Exception e) {e.printStackTrace();} finally {if (con != null) {con.disconnect();}}return bitmap;}} public class ViewHolder{ ImageView iv;TextView detail;TextView dollar; }@Overridepublic int getCount() {return listCostumes.size();}@Overridepublic Object getItem(int arg0) {return listCostumes.get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}/** * 从文件中拿图片 * @param mActivity * @param imageName 图片名字 * @param path 图片路径 * @return */ private Bitmap getBitmapFromFile(Activity mActivity,String imageName,String path){ Bitmap bitmap = null; if(imageName != null){ File file = null; String real_path = ""; try { if(Util.getInstance().hasSDCard()){ real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path); }else{ real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path); } file = new File(real_path, imageName); if(file.exists()) bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); } catch (Exception e) { e.printStackTrace(); bitmap = null; } } return bitmap; } /** * 将下载好的图片存放到文件中 * @param path 图片路径 * @param mActivity * @param imageName 图片名字 * @param bitmap 图片 * @return */ private boolean setBitmapToFile(String path,Activity mActivity,String imageName,Bitmap bitmap){ File file = null; String real_path = ""; try { if(Util.getInstance().hasSDCard()){ real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path); }else{ real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path); } file = new File(real_path, imageName); if(!file.exists()){ File file2 = new File(real_path + "/"); file2.mkdirs(); } file.createNewFile(); FileOutputStream fos = null; if(Util.getInstance().hasSDCard()){ fos = new FileOutputStream(file); }else{ fos = mActivity.openFileOutput(imageName, Context.MODE_PRIVATE); } if (imageName != null && (imageName.contains(".png") || imageName.contains(".PNG"))){ bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos); } else{ bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos); } fos.flush(); if(fos != null){ fos.close(); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 辅助方法,一般不调用 * @param path * @param mActivity * @param imageName */ private void removeBitmapFromFile(String path,Activity mActivity,String imageName){ File file = null; String real_path = ""; try { if(Util.getInstance().hasSDCard()){ real_path = Util.getInstance().getExtPath() + (path != null && path.startsWith("/") ? path : "/" + path); }else{ real_path = Util.getInstance().getPackagePath(mActivity) + (path != null && path.startsWith("/") ? path : "/" + path); } file = new File(real_path, imageName); if(file != null) file.delete(); } catch (Exception e) { e.printStackTrace(); } } }public class PhotoWallAdapter exte