首页 > 代码库 > LruCache类的相关知识以及代码实现

LruCache类的相关知识以及代码实现

一.LruCache的简单介绍

  1. Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。
  2.  * 当cache已满的时候加入新的item时,在队列尾部的item会被回收。
  3.  * 如果你cache的某个值需要明确释放,重写entryRemoved()
  4.  * 如果key相对应的item丢掉啦,重写create().这简化了调用代码,即使丢失了也总会返回。
  5.  * is limited to 4MiB of bitmaps: 默认cache大小是测量的item的数量,重写sizeof计算不同item的
  6.  *  大小。

二.使用Lrucache来异步加载图片,防止阻塞(缓存图片)

下面是我的一个小程序,使用得到了Lrucache,总共有三个类,代码注释也是很详细的,很适合初学者学习。主要的功能就是形成一个像瀑布的图片墙。

在第三个类中有这个项目的设计思想。大家可以看看,共同进步,谢谢!!!

第一个类

 1 package com.pangzaifei.falls; 2  3 import android.app.Activity; 4 import android.os.Bundle; 5  6 /** 7  * 瀑布流 8  *  9  */10 public class Demo extends Activity {11     @Override12     protected void onCreate(Bundle savedInstanceState) {13         super.onCreate(savedInstanceState);14         setContentView(R.layout.activity_demo);15 16     }17 }

 

第二个类

  1 package com.pangzaifei.falls;  2   3 import android.graphics.Bitmap;  4 import android.graphics.BitmapFactory;  5 import android.graphics.BitmapFactory.Options;  6 import android.support.v4.util.LruCache;  7   8 /**  9  * 图片资源 数据源类 10  *  11  */ 12 public class Images { 13     private static Images images; 14     // Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。 15     // 当cache已满的时候加入新的item时,在队列尾部的item会被回收。 16     // 如果你cache的某个值需要明确释放,重写entryRemoved() 17     // 如果key相对应的item丢掉啦,重写create().这简化了调用代码,即使丢失了也总会返回。 18     // 默认cache大小是测量的item的数量,重写sizeof计算不同item的大小。 19     private LruCache<String, Bitmap> mMemoryCache; 20  21     public Images() { 22         initLrucache();// 初始化lrucache 23     } 24  25     public static Images getInstance() { 26         if (images == null) { 27             images = new Images(); 28         } 29         return images; 30     } 31  32     /** 33      * 初始化lrucache 34      */ 35     private void initLrucache() { 36         // 获取应用程序最大内存 37         long maxSize = Runtime.getRuntime().maxMemory(); 38         // 设置图片缓存大小为程序最大可用内存的1/8. 39         int cacheSize = (int) (maxSize / 8); 40         mMemoryCache = new LruCache<String, Bitmap>(cacheSize); 41     } 42  43     /** 44      * 从LruCache中获取一张图片,如果不存在就返回null 从lrucache中获得key key LruCache的键,传入图片的url地址 45      * return 对应传入的bitmap对象,或者null 46      */ 47     public Bitmap getMemoryCache(String key) { 48         if (mMemoryCache != null) { 49             Bitmap bitmap = mMemoryCache.get(key); 50             if (bitmap != null) { 51                 return bitmap; 52             } 53         } 54         return null; 55     } 56  57     /** 58      * 将图片添加到lrucache中 59      *  60      * @param key 61      *            LruCache的键,这里传入图片的URL地址 62      * @param bitmap 63      *            这里指的是从网络上下载的bitmap对象。 64      */ 65     public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 66         if (getMemoryCache(key) == null) { 67             mMemoryCache.put(key, bitmap); 68         } 69     } 70  71     public static final String[] imageThumbs = new String[] { 72             "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg", 73             "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg", 74             "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg", 75             "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg", 76             "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg", 77             "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg", 78             "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg", 79             "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg", 80             "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg", 81             "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg", 82             "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg", 83             "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg", 84             "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg", 85             "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg", 86             "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg", 87             "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg", 88             "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg", 89             "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg", 90             "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg", 91             "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg", 92             "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg", 93             "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg", 94             "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg", 95             "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg", 96             "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg", 97             "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg", 98             "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg", 99             "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",100             "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",101             "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",102             "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",103             "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",104             "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",105             "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",106             "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",107             "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",108             "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",109             "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",110             "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",111             "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",112             "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",113             "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",114             "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",115             "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",116             "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",117             "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",118             "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",119             "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",120             "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",121             "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",122             "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg",123             "http://img.my.csdn.net/uploads/201308/31/1377949442_4562.jpg",124             "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg",125             "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg",126             "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg",127             "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",128             "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",129             "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg",130             "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg",131             "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg",132             "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg",133             "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg",134             "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg",135             "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg",136             "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg",137             "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg",138             "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg",139             "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg",140             "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg",141             "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg",142             "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg",143             "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg",144             "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg",145             "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg",146             "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg",147             "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg",148             "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg",149             "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg",150             "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg",151             "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",152             "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",153             "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",154             "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",155             "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",156             "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",157             "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",158             "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",159             "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",160             "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",161             "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",162             "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",163             "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",164             "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",165             "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",166             "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",167             "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",168             "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",169             "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",170             "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",171             "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",172             "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",173             "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",174             "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg",175             "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg",176             "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg",177             "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg",178             "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",179             "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",180             "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg",181             "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg",182             "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg",183             "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg",184             "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg",185             "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg",186             "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg",187             "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg",188             "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg",189             "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg",190             "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg",191             "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg",192             "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg",193             "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg",194             "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg",195             "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg",196             "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg",197             "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg",198             "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg",199             "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg",200             "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg",201             "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg",202             "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",203             "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",204             "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",205             "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",206             "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",207             "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",208             "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",209             "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",210             "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",211             "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",212             "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",213             "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",214             "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",215             "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",216             "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",217             "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",218             "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",219             "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",220             "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",221             "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",222             "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",223             "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",224             "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",225             "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg",226             "http://img.my.csdn.net/uploads/201309/01/1378037235_3453.jpg",227             "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg",228             "http://img.my.csdn.net/uploads/201309/01/1378037235_9280.jpg",229             "http://img.my.csdn.net/uploads/201309/01/1378037234_3539.jpg",230             "http://img.my.csdn.net/uploads/201309/01/1378037234_6318.jpg",231             "http://img.my.csdn.net/uploads/201309/01/1378037194_2965.jpg",232             "http://img.my.csdn.net/uploads/201309/01/1378037193_1687.jpg",233             "http://img.my.csdn.net/uploads/201309/01/1378037193_1286.jpg",234             "http://img.my.csdn.net/uploads/201309/01/1378037192_8379.jpg",235             "http://img.my.csdn.net/uploads/201309/01/1378037178_9374.jpg",236             "http://img.my.csdn.net/uploads/201309/01/1378037177_1254.jpg",237             "http://img.my.csdn.net/uploads/201309/01/1378037177_6203.jpg",238             "http://img.my.csdn.net/uploads/201309/01/1378037152_6352.jpg",239             "http://img.my.csdn.net/uploads/201309/01/1378037151_9565.jpg",240             "http://img.my.csdn.net/uploads/201309/01/1378037151_7904.jpg",241             "http://img.my.csdn.net/uploads/201309/01/1378037148_7104.jpg",242             "http://img.my.csdn.net/uploads/201309/01/1378037129_8825.jpg",243             "http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg",244             "http://img.my.csdn.net/uploads/201309/01/1378037128_3531.jpg",245             "http://img.my.csdn.net/uploads/201309/01/1378037127_1085.jpg",246             "http://img.my.csdn.net/uploads/201309/01/1378037095_7515.jpg",247             "http://img.my.csdn.net/uploads/201309/01/1378037094_8001.jpg",248             "http://img.my.csdn.net/uploads/201309/01/1378037093_7168.jpg",249             "http://img.my.csdn.net/uploads/201309/01/1378037091_4950.jpg",250             "http://img.my.csdn.net/uploads/201308/31/1377949643_6410.jpg",251             "http://img.my.csdn.net/uploads/201308/31/1377949642_6939.jpg",252             "http://img.my.csdn.net/uploads/201308/31/1377949630_4505.jpg",253             "http://img.my.csdn.net/uploads/201308/31/1377949630_4593.jpg",254             "http://img.my.csdn.net/uploads/201308/31/1377949629_7309.jpg",255             "http://img.my.csdn.net/uploads/201308/31/1377949629_8247.jpg",256             "http://img.my.csdn.net/uploads/201308/31/1377949615_1986.jpg",257             "http://img.my.csdn.net/uploads/201308/31/1377949614_8482.jpg",258             "http://img.my.csdn.net/uploads/201308/31/1377949614_3743.jpg",259             "http://img.my.csdn.net/uploads/201308/31/1377949614_4199.jpg",260             "http://img.my.csdn.net/uploads/201308/31/1377949599_3416.jpg",261             "http://img.my.csdn.net/uploads/201308/31/1377949599_5269.jpg",262             "http://img.my.csdn.net/uploads/201308/31/1377949598_7858.jpg",263             "http://img.my.csdn.net/uploads/201308/31/1377949598_9982.jpg",264             "http://img.my.csdn.net/uploads/201308/31/1377949578_2770.jpg",265             "http://img.my.csdn.net/uploads/201308/31/1377949578_8744.jpg",266             "http://img.my.csdn.net/uploads/201308/31/1377949577_5210.jpg",267             "http://img.my.csdn.net/uploads/201308/31/1377949577_1998.jpg",268             "http://img.my.csdn.net/uploads/201308/31/1377949482_8813.jpg",269             "http://img.my.csdn.net/uploads/201308/31/1377949481_6577.jpg",270             "http://img.my.csdn.net/uploads/201308/31/1377949480_4490.jpg",271             "http://img.my.csdn.net/uploads/201308/31/1377949455_6792.jpg",272             "http://img.my.csdn.net/uploads/201308/31/1377949455_6345.jpg",273             "http://img.my.csdn.net/uploads/201308/31/1377949442_4553.jpg",274             "http://img.my.csdn.net/uploads/201308/31/1377949441_8987.jpg",275             "http://img.my.csdn.net/uploads/201308/31/1377949441_5454.jpg",276             "http://img.my.csdn.net/uploads/201308/31/1377949454_6367.jpg" };277 278     /**279      * 将大图缩放280      * 281      * @param path282      * @param mClolumnWidth283      */284     public Bitmap decodeSimpleBitMapFromResource(String path, int mClolumnWidth) {285         //第一次解析将inJustDecodeBounds设置为true,来获取图片的大小286         final Options options = new Options();287         options.inJustDecodeBounds = true;288         Bitmap bitmap = BitmapFactory.decodeFile(path, options);289         //调用方法计算insampleSize的值290         options.inSampleSize = decodeSimpleSize(options, mClolumnWidth);291         //使用获取到的inSampleSize的值292         options.inJustDecodeBounds = false;293         return BitmapFactory.decodeFile(path, options);294 295     }296 297     /**298      * 获得simpleSize299      * 300      * @param options301      * @return302      */303     private int decodeSimpleSize(Options options, int reqwidth) {304         //源图片的宽度305         int width = options.outWidth;306         int simplesize = 1;307         if (width > reqwidth) {308             //计算出实际宽度和目标宽度的比率309             simplesize = Math.round(width / reqwidth);310         }311         return simplesize;312     }313 }

第三个类

  1 package com.pangzaifei.falls;  2   3 import java.io.BufferedInputStream;  4 import java.io.BufferedOutputStream;  5 import java.io.File;  6 import java.io.FileOutputStream;  7 import java.io.IOException;  8 import java.io.InputStream;  9 import java.net.HttpURLConnection; 10 import java.net.URL; 11 import java.util.ArrayList; 12 import java.util.HashSet; 13 import java.util.List; 14 import java.util.Set; 15  16 import android.content.Context; 17 import android.graphics.Bitmap; 18 import android.graphics.BitmapFactory; 19 import android.os.AsyncTask; 20 import android.os.Environment; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.util.AttributeSet; 24 import android.view.MotionEvent; 25 import android.view.View; 26 import android.view.View.OnTouchListener; 27 import android.widget.ImageView; 28 import android.widget.ImageView.ScaleType; 29 import android.widget.LinearLayout; 30 import android.widget.ScrollView; 31 import android.widget.Toast; 32  33 /** 34  * 瀑布流类          <主要用到了LruCache类,缓存图片 > 35  *  36  * 原理: 1:创建3个linearlayout,设置他们的宽度,将获得的图片压缩成和3个linearlayout一样的宽度, 37  * 然后根据3个linearlayout的高度来判断,将bitmap添加到哪一个linearlayout中 38  * 2:翻页处理,根据手势抬起的位置和滑动的末尾处来进行翻页 39  *  40  */ 41 /* 42 ScrollView原理 43       视图的滚动过程,其实是在不断修改原点坐标。当手指触摸后,ScrollView会暂时拦截触摸事件, 44       使用一个计时器。假如在计时器到点后没有发生手指移动事件,那么ScrollView发送tracking events到被点击的subView; 45       若是在计时器到点后发生了移动事件,那么ScrollView取消tracking自己促发滚动。 46 */ 47 /*首先还是讲一下实现原理,瀑布流的布局方式虽然看起来好像排列的很随意,其实它是有很科学的排列规则的。 48  * 整个界面会根据屏幕的宽度划分成等宽的若干列,由于手机的屏幕不是很大,这里我们就分成三列。每当需要添加一张图片时, 49  * 会将这张图片的宽度压缩成和列一样宽,再按照同样的压缩比例对图片的高度进行压缩,然后在这三列中找出当前高度最小的一列, 50  * 将图片添加到这一列中。之后每当需要添加一张新图片时,都去重复上面的操作,就会形成瀑布流格局的照片墙 51 */ 52 public class PhotoFallScrollView extends ScrollView implements OnTouchListener { 53     /** 54      * 记录当前已加载到第几页 55      */ 56     private static int page; 57     /** 58      * 每页显示多少张图片的数量 59      */ 60     private static final int PAGE_SIZE = 8; 61     private Context mContext; 62     /** 63      * 数据源图片 64      */ 65     private Images mImagesThoumb; 66     /** 67      * task请求集合 68      */ 69     private Set<DownLoadTask> mTasks; 70     //判断是否是第一次进入 71     boolean isFirstEntr = true; 72      73     /**三列布局 74      *  75      */ 76     private LinearLayout mFirstColumn; 77     private LinearLayout mSecondColumn; 78     private LinearLayout mThirdColumn; 79     //当前第一列,第二列,第三列的高度 80     private int mFirstColumnHeight; 81     private int mSecondColumnHeight; 82     private int mThirdColumnHeight; 83     /**  84      * 每一列的宽度  85      */  86     private int mClolumnWidth; 87  88     private long mDelay = 5; 89     /** 90      * 上次滑动的最后位置 91      */ 92     private static int lastScrollY = -1; 93  94     /** 95      * 是否已加载过一次layout,这里onLayout中的初始化只需加载一次 96      */ 97     private boolean loadOnce; 98     /** 99      * 存放图片的集合100      */101     private List<ImageView> mImageViewList = new ArrayList<ImageView>();102 103     public PhotoFallScrollView(Context context, AttributeSet attrs, int defStyle) {104         super(context, attrs, defStyle);105         this.mContext = context;106         init();107     }108 109     public PhotoFallScrollView(Context context, AttributeSet attrs) {110         super(context, attrs);111         this.mContext = context;112         init();113     }114 115     public PhotoFallScrollView(Context context) {116         super(context);117         this.mContext = context;118         init();119     }120 121     /**122      * 初始化123      */124     private void init() {125         mImagesThoumb = Images.getInstance();126         mTasks = new HashSet<DownLoadTask>();127         setOnTouchListener(this);128     }129 130     /**131      * 进行一些关键性的初始化操作,获取MyScrollView的高度以及得到第一列的宽度值。132      * 并在这里开始加载第一页的图片。 133      *134      */135     @Override136     protected void onLayout(boolean changed, int l, int t, int r, int b) {137         super.onLayout(changed, l, t, r, b);138 139         // 第一次进入就加载第一页的图片140         if (changed && !loadOnce) {141             mScrollViewHeight = this.getHeight();142             mScrollLayout = this.getChildAt(0);//从id的值为0处开始获取143             mFirstColumn = (LinearLayout) findViewById(R.id.first_column);144             mSecondColumn = (LinearLayout) findViewById(R.id.second_column);145             mThirdColumn = (LinearLayout) findViewById(R.id.third_column);146             //获取每一列的宽度147             mClolumnWidth = mFirstColumn.getWidth();148             loadOnce = true;149             //开始加载下一页的图片150             loadMoreImages();151         }152     }153 154     /**开始加载下一页的图片,每张图片都会开启一个异步线程去下载。155      * 加载图片156      */157     private void loadMoreImages() {158         if (hashSdcard()) {159 160             // 根据页数加载图片161             int startIndex = page * PAGE_SIZE;162             int endIndex = page * PAGE_SIZE + PAGE_SIZE;163 164             if (startIndex < mImagesThoumb.imageThumbs.length) {165                 if (endIndex > mImagesThoumb.imageThumbs.length) {166                     endIndex = mImagesThoumb.imageThumbs.length;167                 }168                 for (int i = startIndex; i < endIndex; i++) {169                     String imageUrl = mImagesThoumb.imageThumbs[i].toString();170                     if (imageUrl != null && !"".equals(imageUrl)) {171                         //开始下载图片172                         downLoadData(imageUrl);173                     }174                 }175                 page++;176             } else {177                 Toast.makeText(mContext, "没有更多图片了", 0).show();178             }179         } else {180             Toast.makeText(mContext, "无sdcard", 0).show();181         }182     }183 184     /**185      * 下载186      * 187      * @param imageUrl188      */189     private void downLoadData(String imageUrl) {190         DownLoadTask task = new DownLoadTask();191         mTasks.add(task);192         //执行193         task.execute(imageUrl);194     }195 196     /**197      *异步下载图片198      */199     public class DownLoadTask extends AsyncTask<String, String, Bitmap> {200         /** 201          * 图片的URL地址 202          */203         private String mImageUrl;204 205         @Override206         protected Bitmap doInBackground(String... params) {207             try {208                 mImageUrl = params[0];209                 Bitmap bitmapFromMemory = mImagesThoumb210                         .getMemoryCache(mImageUrl);211                 if (bitmapFromMemory != null) {212                     return bitmapFromMemory;213                 }214                 if (hashSdcard()) {215                     Bitmap bitmap = loadImage(mImageUrl);216                     return bitmap;217                 } else {218                     Toast.makeText(mContext, "无sdcard,无法获取图片", 0).show();219                 }220 221             } catch (Exception e) {222                 e.printStackTrace();223             }224             return null;225         }226 227         @Override228         protected void onPostExecute(Bitmap bitmap) {229             super.onPostExecute(bitmap);230             // 展示图片231             if (bitmap != null) {232                 // 1.缩放图片233                 // 2.新建ImageView234                 // 3.找到需要的linerlayout添加imageView235                 float width = bitmap.getWidth();236                 float radio = width / mFirstColumn.getWidth();237                 float scaleHeight = bitmap.getHeight() / radio;238                 addImage(bitmap, mFirstColumn.getWidth(), scaleHeight);239             }240             mTasks.remove(this);241         }242 243         /** 244          * 向ImageView中添加一张图片 245          *  246          * @param bitmap 247          *            待添加的图片 248          * @param width 249          *            图片的宽度 250          * @param scaleHeight 251          *            图片的高度 252          */  253         public void addImage(Bitmap bitmap, float width, float scaleHeight) {254             // 生成缩放的iv255             ImageView iv = new ImageView(mContext);256             android.view.ViewGroup.LayoutParams params = new LayoutParams(257                     (int) width, (int) scaleHeight);258             iv.setLayoutParams(params);259             if (bitmap != null) {260                 // 解决默认图片有大有小的问题261                 iv.setScaleType(ScaleType.FIT_XY);262                 iv.setPadding(5, 5, 5, 5);263 264                 iv.setImageBitmap(bitmap);265                 iv.setTag(R.string.iamgurl, mImageUrl);266                 findColumnToAdd(iv, (int) scaleHeight).addView(iv);267                 mImageViewList.add(iv);268             }269         }270 271     }272 273     /**将图片下载到SD卡缓存起来。274      * @param imageUrl 图片的URL地址。 275      * @return276      * @throws IOException277      */278     private Bitmap downLoad(String imageUrl) throws IOException {279         BufferedInputStream bis = null;280         FileOutputStream fos = null;281         BufferedOutputStream bos = null;282         HttpURLConnection conn = null;283         File imageFile = null;284         try {285             URL url = new URL(imageUrl);286             conn = (HttpURLConnection) url.openConnection();287             conn.setReadTimeout(10000);288             conn.setConnectTimeout(5000);289             conn.setDoInput(true);290             conn.setDoOutput(true);291             InputStream is = conn.getInputStream();292             imageFile = new File(getImagePath(imageUrl));293             bis = new BufferedInputStream(is);294             fos = new FileOutputStream(imageFile);295             bos = new BufferedOutputStream(fos);296             int len = 0;297             byte[] buffer = new byte[1024];298             while ((len = bis.read(buffer)) != -1) {299                 bos.write(buffer, 0, len);300                 bos.flush();301             }302         } catch (Exception e) {303             e.printStackTrace();304         } finally {305             if (bis != null) {306                 bis.close();307             }308             if (bos != null) {309                 bos.close();310             }311             if (conn != null) {312                 conn.disconnect();313             }314         }315         // 如果imageFile不为null,将图片添加到memory中316         if (imageFile != null) {317             Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getPath());318             mImagesThoumb.addBitmapToMemoryCache(imageUrl, bitmap);319             return bitmap;320         }321         return null;322 323     }324 325    326     /** 327      * 根据传入的URL,对图片进行加载。如果这张图片已经存在于SD卡中,则直接从SD卡里读取,否则就从网络上下载。 328      *  329      * @param imageUrl 330      *            图片的URL地址 331      * @return 加载到内存的图片。 332      * 判断图片sdcard是否有图片,如果有就用,没有就下载333      */  334     public Bitmap loadImage(String mImageUrl) throws Exception {335         File file = new File(getImagePath(mImageUrl));336         if (!file.exists()) {337             downLoad(mImageUrl);338         }339 340         if (mImageUrl != null) {341             // 处理本地图片,设置大小防止oom342             Bitmap bitmap = mImagesThoumb.decodeSimpleBitMapFromResource(343                     file.getPath(), mClolumnWidth);344             // Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());345             if (bitmap != null) {346                 mImagesThoumb.addBitmapToMemoryCache(mImageUrl, bitmap);347                 return bitmap;348             }349         }350         return null;351     }352 353     /** 354      * 找到此时应该添加图片的一列。原则就是对三列的高度进行判断,当前高度最小的一列就是应该添加的一列。 355      *  356      * @param iv 357      * @param imageHeight 358      * @return 应该添加图片的一列 359      */ 360     private LinearLayout findColumnToAdd(ImageView iv, int imageHeight) {361         if (mFirstColumnHeight <= mSecondColumnHeight) {362             if (mFirstColumnHeight <= mThirdColumnHeight) {363                 iv.setTag(R.string.border_top, mFirstColumnHeight);364                 mFirstColumnHeight += imageHeight;365                 iv.setTag(R.string.border_bottom, mFirstColumnHeight);366                 return mFirstColumn;367             }368             iv.setTag(R.string.border_top, mThirdColumnHeight);369             mThirdColumnHeight += imageHeight;370             iv.setTag(R.string.border_bottom, mThirdColumnHeight);371             return mThirdColumn;372 373         } else {374             if (mSecondColumnHeight <= mThirdColumnHeight) {375                 iv.setTag(R.string.border_top, mSecondColumnHeight);376                 mSecondColumnHeight += imageHeight;377                 iv.setTag(R.string.border_bottom, mSecondColumnHeight);378                 return mSecondColumn;379             }380             iv.setTag(R.string.border_top, mThirdColumnHeight);381             mThirdColumnHeight += imageHeight;382             iv.setTag(R.string.border_bottom, mThirdColumnHeight);383             return mThirdColumn;384         }385     }386 387     /**获取图片的本地存储路径。 388      * 获得file地址389      * 390      * @param imageUrl 图片的URL地址。391      * @return 图片的本地存储路径。392      */393     private String getImagePath(String imageUrl) {394         int lastIndexOf = imageUrl.lastIndexOf("/");395         String imageName = imageUrl.substring(lastIndexOf + 1);396         String imageDir = Environment.getExternalStorageDirectory().getPath()397                 + "/pangzaifei/";398         File file = new File(imageDir);399         if (!file.exists()) {400             file.mkdir();401         }402         String imagePath = imageDir + imageName;403         return imagePath;404     }405 406     /**判断手机是否有sd卡407      * 获得图片的名字408      * 409      * @param imageUrl410      */411 412     private boolean hashSdcard() {413         if (Environment.getExternalStorageState().equals(414                 Environment.MEDIA_MOUNTED)) {415             return true;416         }417         return false;418     }419 420     @Override421     /**422      * 当手势抬起时,开始每个5毫秒计算位置423      * 监听用户的触屏事件,如果用户手指离开屏幕则开始进行滚动检测。 424      */425     public boolean onTouch(View v, MotionEvent event) {426         if (event.getAction() == MotionEvent.ACTION_UP) {427             // 发送handler428             Message msg = mHandler.obtainMessage();429             msg.obj = this;430             mHandler.sendMessageDelayed(msg, mDelay);431         }432         return false;433     }434 435     /**436      * 在Handler中进行图片可见性检测的判断,以及加载更多图片的操作437      */438     private Handler mHandler = new Handler() {439 440         @Override441         public void handleMessage(Message msg) {442             super.handleMessage(msg);443             // 判断是否已经滑到了最低处,如果滑到了最低处,则加载更多页面,否则继续发送handler扫描444             PhotoFallScrollView scrollView = (PhotoFallScrollView) msg.obj;445             int scrollY = scrollView.getScrollY();446             //如果当前的滚动位置和上次相同,表示已停止滚动447             if (scrollY == lastScrollY) {448             // 当滚动的最底部,并且当前没有正在下载的任务时,开始加载下一页的图片  449                 if (mScrollViewHeight + scrollY >= mScrollLayout.getHeight()450                         && mTasks.isEmpty()) {451                     scrollView.loadMoreImages();452                 }453                 scrollView.checkVisibile();454             } else {455                 lastScrollY = scrollY;456                 Message message = new Message();457                 message.obj = scrollView;458                //5毫秒后在对滚动位置进行判断459                 mHandler.sendMessageDelayed(message, mDelay);460             }461         }462 463     };464     /**465      * MyScrollView布局的高度。466      */467     private int mScrollViewHeight;468     /** 469      * MyScrollView下的直接子布局。 470      */  471     private View mScrollLayout;472 473     /**474      * 遍历imageview中的每一张图片,对图片的可见性进行检测,如果图片已经离开屏幕可见范围,475      * 则将图片替换成一张空图476      * 想不可见的变为空图片477      */478     protected void checkVisibile() {479         if (mImageViewList != null && mImageViewList.size() > 0) {480             for (int i = 0; i < mImageViewList.size(); i++) {481                 ImageView iv = mImageViewList.get(i);482                 int borderTop = (Integer) iv.getTag(R.string.border_top);483                 int borderBottom = (Integer) iv.getTag(R.string.border_bottom);484                 if (borderBottom > getScrollY()485                         && borderTop < getScrollY() + mScrollViewHeight) {486                     String imageUrl = (String) iv.getTag(R.string.iamgurl);487                     if (imageUrl != null && !"".equals(imageUrl)) {488                         Bitmap bitmap = mImagesThoumb.getMemoryCache(imageUrl);489                         if (bitmap != null) {490                             iv.setImageBitmap(bitmap);491                         } else {492                             downLoadData(imageUrl);493                         }494                     }495                 } else {496                     //离开屏幕加载空图497                     iv.setImageResource(R.drawable.empty_photo);498                 }499 500             }501         }502     }503 }

 

LruCache类的相关知识以及代码实现