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     @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             "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 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 }
时间: 2024-10-10 06:24:06

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

python类的相关知识第二部分

类的继承.多态.封装 一.类的继承 1.应用场景: 类大部分功能相同,大类包含小类的情况 例如: 动物类 共性:都要吃喝拉撒.都有头有脚 特性: 猫类.走了很轻,叫声特别,喜欢白天睡觉 狗类.的叫声很大,晚上睡觉 2.继承顺序 在python2版本中多重继承有分两种继承循序 (1).一直往上找 .找到最高级的父类再重另外一个分支找,直到找到为止. (2).一直往上找,找到最高级父类的下一层后就不找了.从另外一个分支找,另外一个分支没找到最后才找最高级的父类. 再python3中只有第一种继承循序

OC笔记:类的基础知识及代码示例

类 1.类的定义: 类=属性+方法: -属性代表类的特征 -方法是类能对变化做出的反应 类定义的格式:类的声明和类的实现组成 -接口(类的声明):@interface 类名:基类的名字 .类名首字母要大写 .冒号表示继承关系,冒号后面的是类的父类 .NSObject是OC所有类的基类 .类的声明放在“类名+.h”文件中,要由两部分组成:实例变量和方法 -实现(类的实现):@implementation类名 .方法实现 -都用@end结束c 2.类的使用: OC中,对象通过指针来声明   如:Cl

类的相关知识

isinstance(obj,cls) 检测obj是否是类cls的对象,是True,不是False class Foo(object): pass obj = Foo() isinstance(obj, Foo)   issubclass(sub,super) 检测sub类是否是super类的派生类 class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)     异常处理 语法: try: #固定格式,有可能出现异常的代

类的相关知识(封装、继承、多态、方法、构造方法、接口、抽象类、静态方法、静态变量等)

类 通过抽象,得到的某一个事物的共同特征. 1.类是抽象的,概念的,代表一类事物,比如人类,猫类-- 2.对象是具体的,实际的,代表一个具体事物 3.类是对象的模板,对象是类的一个个体,实例 class Cat           // Java中类名的首字母大写 { //下面的就是类的成员变量.属性 Int age; String name; String color; } 类的结构: Package 包名: Class 类名 extends 父类 implements 接口名 { 成员变量(

【Python学习之旅】---多态(类的相关知识)

#多态反应的是执行时候的状态,不同对象调用的相同方法,调用同一个类,但运行结果不一样,属于继承的一种体现机制.class H2O: def __init__(self,name,wendu): self.name=name self.wendu=wendu def turn_ice(self): if self.wendu < 0: print('[%s]温度太低成冰了' %self.name) elif self.wendu > 0 and self.wendu <100 : prin

【Python学习之旅】---多态(类的相关知识,面向对象三大特性:继承-多态-封装)

class Name: __a='你是猪' #封装变量a def __init__(self,name): self.name=name def get_name(self): print('我叫%s' %self.name) n1=Name('陈宇霞')print(Name.__dict__) #查看类属性字典print(n1._Name__a) #可以通过此种方式调用__a ,没有真正的封装 #执行结果: {'__module__': '__main__', '_Name__a': '你是猪

【Python学习之旅】---封装与反射(类的相关知识,面向对象三大特性:继承-多态-封装)

#第一层封装:定义类#第二层封装:区分内外,有些属性只能内部使用,外部不能 class Name: __a='你是猪' #封装变量a def __init__(self,name): self.name=name def get_name(self): print('我叫%s' %self.name) n1=Name('陈宇霞')print(Name.__dict__) #查看类属性字典print(n1._Name__a) #可以通过此种方式调用__a ,没有真正的封装 #真正的封装:区分内外,

类的相关知识01

黑马程序员---Objective-C基础学习---类、对象、方法相关知识笔记

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 类.对象.方法相关知识笔记 Objective-C相对于C语言有了面向对象的特性,但是ObjC又没有其他面向对象语言那么多语法特性,ObjC本身对面向对象进行了精简.下面是一些相关知识笔记. 类定义 成员变量 方法和属性 self关键字 类定义 在C#.Java等其他高级语言中定义一个类是相当简单点的,直接一个关键字class加一对大括号基本就完成了,但是在ObjC中类的定义相对变化比较大.现