一.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     @Override
12     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             "//img-my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
 73             "//img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
 74             "//img-my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
 75             "//img-my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
 76             "//img-my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
 77             "//img-my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
 78             "//img-my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
 79             "//img-my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
 80             "//img-my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
 81             "//img-my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
 82             "//img-my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
 83             "//img-my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
 84             "//img-my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
 85             "//img-my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
 86             "//img-my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
 87             "//img-my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
 88             "//img-my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
 89             "//img-my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
 90             "//img-my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
 91             "//img-my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
 92             "//img-my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
 93             "//img-my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
 94             "//img-my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
 95             "//img-my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
 96             "//img-my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
 97             "//img-my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
 98             "//img-my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
 99             "//img-my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
100             "//img-my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
101             "//img-my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
102             "//img-my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
103             "//img-my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
104             "//img-my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
105             "//img-my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
106             "//img-my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
107             "//img-my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
108             "//img-my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
109             "//img-my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
110             "//img-my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
111             "//img-my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
112             "//img-my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
113             "//img-my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
114             "//img-my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
115             "//img-my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
116             "//img-my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
117             "//img-my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
118             "//img-my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
119             "//img-my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
120             "//img-my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
121             "//img-my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
122             "//img-my.csdn.net/uploads/201308/31/1377949454_6367.jpg",
123             "//img-my.csdn.net/uploads/201308/31/1377949442_4562.jpg",
124             "//img-my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
125             "//img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
126             "//img-my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
127             "//img-my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
128             "//img-my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
129             "//img-my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
130             "//img-my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
131             "//img-my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
132             "//img-my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
133             "//img-my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
134             "//img-my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
135             "//img-my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
136             "//img-my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
137             "//img-my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
138             "//img-my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
139             "//img-my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
140             "//img-my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
141             "//img-my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
142             "//img-my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
143             "//img-my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
144             "//img-my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
145             "//img-my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
146             "//img-my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
147             "//img-my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
148             "//img-my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
149             "//img-my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
150             "//img-my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
151             "//img-my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
152             "//img-my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
153             "//img-my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
154             "//img-my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
155             "//img-my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
156             "//img-my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
157             "//img-my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
158             "//img-my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
159             "//img-my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
160             "//img-my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
161             "//img-my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
162             "//img-my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
163             "//img-my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
164             "//img-my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
165             "//img-my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
166             "//img-my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
167             "//img-my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
168             "//img-my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
169             "//img-my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
170             "//img-my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
171             "//img-my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
172             "//img-my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
173             "//img-my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
174             "//img-my.csdn.net/uploads/201308/31/1377949454_6367.jpg",
175             "//img-my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
176             "//img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
177             "//img-my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
178             "//img-my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
179             "//img-my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
180             "//img-my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
181             "//img-my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
182             "//img-my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
183             "//img-my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
184             "//img-my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
185             "//img-my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
186             "//img-my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
187             "//img-my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
188             "//img-my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
189             "//img-my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
190             "//img-my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
191             "//img-my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
192             "//img-my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
193             "//img-my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
194             "//img-my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
195             "//img-my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
196             "//img-my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
197             "//img-my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
198             "//img-my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
199             "//img-my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
200             "//img-my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
201             "//img-my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
202             "//img-my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
203             "//img-my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
204             "//img-my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
205             "//img-my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
206             "//img-my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
207             "//img-my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
208             "//img-my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
209             "//img-my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
210             "//img-my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
211             "//img-my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
212             "//img-my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
213             "//img-my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
214             "//img-my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
215             "//img-my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
216             "//img-my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
217             "//img-my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
218             "//img-my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
219             "//img-my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
220             "//img-my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
221             "//img-my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
222             "//img-my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
223             "//img-my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
224             "//img-my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
225             "//img-my.csdn.net/uploads/201308/31/1377949454_6367.jpg",
226             "//img-my.csdn.net/uploads/201309/01/1378037235_3453.jpg",
227             "//img-my.csdn.net/uploads/201309/01/1378037235_7476.jpg",
228             "//img-my.csdn.net/uploads/201309/01/1378037235_9280.jpg",
229             "//img-my.csdn.net/uploads/201309/01/1378037234_3539.jpg",
230             "//img-my.csdn.net/uploads/201309/01/1378037234_6318.jpg",
231             "//img-my.csdn.net/uploads/201309/01/1378037194_2965.jpg",
232             "//img-my.csdn.net/uploads/201309/01/1378037193_1687.jpg",
233             "//img-my.csdn.net/uploads/201309/01/1378037193_1286.jpg",
234             "//img-my.csdn.net/uploads/201309/01/1378037192_8379.jpg",
235             "//img-my.csdn.net/uploads/201309/01/1378037178_9374.jpg",
236             "//img-my.csdn.net/uploads/201309/01/1378037177_1254.jpg",
237             "//img-my.csdn.net/uploads/201309/01/1378037177_6203.jpg",
238             "//img-my.csdn.net/uploads/201309/01/1378037152_6352.jpg",
239             "//img-my.csdn.net/uploads/201309/01/1378037151_9565.jpg",
240             "//img-my.csdn.net/uploads/201309/01/1378037151_7904.jpg",
241             "//img-my.csdn.net/uploads/201309/01/1378037148_7104.jpg",
242             "//img-my.csdn.net/uploads/201309/01/1378037129_8825.jpg",
243             "//img-my.csdn.net/uploads/201309/01/1378037128_5291.jpg",
244             "//img-my.csdn.net/uploads/201309/01/1378037128_3531.jpg",
245             "//img-my.csdn.net/uploads/201309/01/1378037127_1085.jpg",
246             "//img-my.csdn.net/uploads/201309/01/1378037095_7515.jpg",
247             "//img-my.csdn.net/uploads/201309/01/1378037094_8001.jpg",
248             "//img-my.csdn.net/uploads/201309/01/1378037093_7168.jpg",
249             "//img-my.csdn.net/uploads/201309/01/1378037091_4950.jpg",
250             "//img-my.csdn.net/uploads/201308/31/1377949643_6410.jpg",
251             "//img-my.csdn.net/uploads/201308/31/1377949642_6939.jpg",
252             "//img-my.csdn.net/uploads/201308/31/1377949630_4505.jpg",
253             "//img-my.csdn.net/uploads/201308/31/1377949630_4593.jpg",
254             "//img-my.csdn.net/uploads/201308/31/1377949629_7309.jpg",
255             "//img-my.csdn.net/uploads/201308/31/1377949629_8247.jpg",
256             "//img-my.csdn.net/uploads/201308/31/1377949615_1986.jpg",
257             "//img-my.csdn.net/uploads/201308/31/1377949614_8482.jpg",
258             "//img-my.csdn.net/uploads/201308/31/1377949614_3743.jpg",
259             "//img-my.csdn.net/uploads/201308/31/1377949614_4199.jpg",
260             "//img-my.csdn.net/uploads/201308/31/1377949599_3416.jpg",
261             "//img-my.csdn.net/uploads/201308/31/1377949599_5269.jpg",
262             "//img-my.csdn.net/uploads/201308/31/1377949598_7858.jpg",
263             "//img-my.csdn.net/uploads/201308/31/1377949598_9982.jpg",
264             "//img-my.csdn.net/uploads/201308/31/1377949578_2770.jpg",
265             "//img-my.csdn.net/uploads/201308/31/1377949578_8744.jpg",
266             "//img-my.csdn.net/uploads/201308/31/1377949577_5210.jpg",
267             "//img-my.csdn.net/uploads/201308/31/1377949577_1998.jpg",
268             "//img-my.csdn.net/uploads/201308/31/1377949482_8813.jpg",
269             "//img-my.csdn.net/uploads/201308/31/1377949481_6577.jpg",
270             "//img-my.csdn.net/uploads/201308/31/1377949480_4490.jpg",
271             "//img-my.csdn.net/uploads/201308/31/1377949455_6792.jpg",
272             "//img-my.csdn.net/uploads/201308/31/1377949455_6345.jpg",
273             "//img-my.csdn.net/uploads/201308/31/1377949442_4553.jpg",
274             "//img-my.csdn.net/uploads/201308/31/1377949441_8987.jpg",
275             "//img-my.csdn.net/uploads/201308/31/1377949441_5454.jpg",
276             "//img-my.csdn.net/uploads/201308/31/1377949454_6367.jpg" };
277 
278     /**
279      * 将大图缩放
280      * 
281      * @param path
282      * @param mClolumnWidth
283      */
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      * 获得simpleSize
299      * 
300      * @param options
301      * @return
302      */
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     @Override
136     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 imageUrl
188      */
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         @Override
206         protected Bitmap doInBackground(String... params) {
207             try {
208                 mImageUrl = params[0];
209                 Bitmap bitmapFromMemory = mImagesThoumb
210                         .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         @Override
228         protected void onPostExecute(Bitmap bitmap) {
229             super.onPostExecute(bitmap);
230             // 展示图片
231             if (bitmap != null) {
232                 // 1.缩放图片
233                 // 2.新建ImageView
234                 // 3.找到需要的linerlayout添加imageView
235                 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             // 生成缩放的iv
255             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      * @return
276      * @throws IOException
277      */
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             // 处理本地图片,设置大小防止oom
342             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 imageUrl
410      */
411 
412     private boolean hashSdcard() {
413         if (Environment.getExternalStorageState().equals(
414                 Environment.MEDIA_MOUNTED)) {
415             return true;
416         }
417         return false;
418     }
419 
420     @Override
421     /**
422      * 当手势抬起时,开始每个5毫秒计算位置
423      * 监听用户的触屏事件,如果用户手指离开屏幕则开始进行滚动检测。 
424      */
425     public boolean onTouch(View v, MotionEvent event) {
426         if (event.getAction() == MotionEvent.ACTION_UP) {
427             // 发送handler
428             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         @Override
441         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 }

 

posted on 2014-09-23 09:37  xuan轩  阅读(663)  评论(0编辑  收藏  举报