1.三级缓存设计步骤:
* 从内存中取图片
* 从本地文件中取图片 向内存中保持一份 * 请求网络图片,获取图片,显示到控件上 向内存存一份 向本地文件中存一份1 package com.atguigu.beijingnews.utils; 2 3 import android.graphics.Bitmap; 4 import android.os.Handler; 5 6 public class BitmapCacheUtils { 7 8 /** 9 * 网络缓存工具类10 */11 private NetCacheUtils netCacheUtils;12 13 /**14 * 本地缓存工具类15 */16 17 private LocalCacheUtils localCacheUtils;18 19 /**20 内存缓存工具类21 */22 private MemoryCacheUtils memoryCacheUtils;23 24 public BitmapCacheUtils(Handler handler) {25 memoryCacheUtils = new MemoryCacheUtils();26 localCacheUtils = new LocalCacheUtils(memoryCacheUtils);27 netCacheUtils = new NetCacheUtils(handler,localCacheUtils,memoryCacheUtils);28 29 }30 31 32 /**33 * 三级缓存设计步骤:34 * * 从内存中取图片35 * * 从本地文件中取图片36 * 向内存中保持一份37 * * 请求网络图片,获取图片,显示到控件上,Hanlder,postion38 * * 向内存存一份39 * * 向本地文件中存一份40 *41 * @param imageUrl42 * @param position43 * @return44 */45 public Bitmap getBitmap(String imageUrl, int position) {46 //1.从内存中取图片47 if (memoryCacheUtils != null) {48 Bitmap bitmap = memoryCacheUtils.getBitmapFromUrl(imageUrl);49 if (bitmap != null) {50 LogUtil.e("内存加载图片成功=="+position);51 return bitmap;52 }53 }54 55 //2.从本地文件中取图片56 if (localCacheUtils != null) {57 Bitmap bitmap = localCacheUtils.getBitmapFromUrl(imageUrl);58 if (bitmap != null) {59 LogUtil.e("本地加载图片成功=="+position);60 return bitmap;61 }62 }63 64 //3.请求网络图片65 netCacheUtils.getBitmapFomNet(imageUrl, position);66 return null;67 }68 }
2.网络缓存
线程池类Executors的使用
public static ExecutorService newCachedThreadPool()
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。
1 package com.atguigu.beijingnews.utils; 2 3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.os.Handler; 6 import android.os.Message; 7 8 import java.io.IOException; 9 import java.io.InputStream;10 import java.net.HttpURLConnection;11 import java.net.URL;12 import java.util.concurrent.ExecutorService;13 import java.util.concurrent.Executors;14 15 public class NetCacheUtils {16 17 /**18 * 请求图片成功19 */20 public static final int SUCESS = 1;21 /**22 * 请求图片失败23 */24 public static final int FAIL = 2;25 private final Handler handler;26 /**27 * 本地缓存工具类28 */29 private final LocalCacheUtils localCacheUtils;30 /**31 * 内存缓存工具类32 */33 private final MemoryCacheUtils memoryCacheUtils;34 /**35 * 线程池类36 */37 private ExecutorService service;38 39 public NetCacheUtils(Handler handler, LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {40 this.handler = handler;41 service = Executors.newFixedThreadPool(10);42 this.localCacheUtils = localCacheUtils;43 this.memoryCacheUtils =memoryCacheUtils;44 }45 46 //联网请求得到图片47 public void getBitmapFomNet(String imageUrl, int position) {48 // new Thread(new MyRunnable(imageUrl,position)).start();49 service.execute(new MyRunnable(imageUrl,position));50 }51 52 class MyRunnable implements Runnable{53 54 private final String imageUrl;55 private final int position;56 57 public MyRunnable(String imageUrl, int position) {58 this.imageUrl = imageUrl;59 this.position = position;60 }61 62 @Override63 public void run() {64 //子线程65 //请求网络图片66 try {67 URL urL = new URL(imageUrl);68 HttpURLConnection connection = (HttpURLConnection) urL.openConnection();69 connection.setRequestMethod("GET");//只能大写70 connection.setConnectTimeout(4000);71 connection.setReadTimeout(4000);72 connection.connect();//可写可不写73 int code = connection.getResponseCode();74 if(code ==200){75 InputStream is = connection.getInputStream();76 Bitmap bitmap = BitmapFactory.decodeStream(is);77 78 //显示到控件上,发消息吧Bitmap发出去和position79 Message msg = Message.obtain();80 msg.what = SUCESS;81 msg.arg1 = position;82 msg.obj = bitmap;83 handler.sendMessage(msg);84 85 //在内存中缓存一份86 memoryCacheUtils.putBitmap(imageUrl,bitmap);87 //在本地中缓存一份88 localCacheUtils.putBitmap(imageUrl,bitmap);89 }90 } catch (IOException e) {91 e.printStackTrace();92 Message msg = Message.obtain();93 msg.what = FAIL;94 msg.arg1 = position;95 handler.sendMessage(msg);96 }97 }98 }99 }
3.本地缓存
File file = new File(CACHE_DIR, fileName); FileInputStream FileOutputStream 文件读写方式
演示把图片移除后,在查看
C:\Users\Administrator>adb shell# cd /mnt/sdcard/atguigu_beijingnewscd /mnt/sdcard/atguigu_beijingnews# rm *rm *1 package com.atguigu.beijingnews.utils; 2 3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.os.Environment; 6 7 import java.io.File; 8 import java.io.FileInputStream; 9 import java.io.FileOutputStream;10 11 public class LocalCacheUtils {12 private final MemoryCacheUtils memoryCacheUtils;13 14 public LocalCacheUtils(MemoryCacheUtils memoryCacheUtils) {15 this.memoryCacheUtils = memoryCacheUtils;16 }17 18 /**19 * 根据Url获取图片20 * @param imageUrl21 * @return22 */23 public Bitmap getBitmapFromUrl(String imageUrl) {24 //判断sdcard是否挂载25 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){26 //保存图片在/mnt/sdcard/beijingnews/http://192.168.21.165:8080/xsxxxx.png27 //保存图片在/mnt/sdcard/beijingnews/llkskljskljklsjklsllsl28 try {29 String fileName = MD5Encoder.encode(imageUrl);//llkskljskljklsjklsllsl30 31 ///mnt/sdcard/beijingnews/llkskljskljklsjklsllsl32 File file = new File(Environment.getExternalStorageDirectory()+"/beijingnews",fileName);33 34 35 36 37 if(file.exists()){38 39 FileInputStream is = new FileInputStream(file);40 Bitmap bitmap = BitmapFactory.decodeStream(is);41 if(bitmap != null){42 memoryCacheUtils.putBitmap(imageUrl,bitmap);43 LogUtil.e("把从本地保持到内存中");44 }45 return bitmap;46 47 }48 49 } catch (Exception e) {50 e.printStackTrace();51 LogUtil.e("图片获取失败");52 }53 }54 55 return null;56 }57 58 /**59 * 根据Url保存图片60 * @param imageUrl url61 * @param bitmap 图片62 */63 public void putBitmap(String imageUrl, Bitmap bitmap) {64 65 //判断sdcard是否挂载66 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){67 //保存图片在/mnt/sdcard/beijingnews/http://192.168.21.165:8080/xsxxxx.png68 //保存图片在/mnt/sdcard/beijingnews/llkskljskljklsjklsllsl69 try {70 String fileName = MD5Encoder.encode(imageUrl);//llkskljskljklsjklsllsl71 72 ///mnt/sdcard/beijingnews/llkskljskljklsjklsllsl73 File file = new File(Environment.getExternalStorageDirectory()+"/beijingnews",fileName);74 75 File parentFile = file.getParentFile();//mnt/sdcard/beijingnews76 if(!parentFile.exists()){77 //创建目录78 parentFile.mkdirs();79 }80 81 82 if(!file.exists()){83 file.createNewFile();84 }85 //保存图片86 bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file));87 88 } catch (Exception e) {89 e.printStackTrace();90 LogUtil.e("图片本地缓存失败");91 }92 }93 94 95 }96 }
4.内存缓存
引用级别
我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。
但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象;另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,
这就有潜在的风险造成应用程序的内存溢出并崩溃。所以看到还有很多相关文章还在推荐用软引用或弱引用 (SoftReference or WeakReference),就有点out了
Android3.0后提出新的方式
LruCache 缓存的集合,把常用的数据,保留起来,把不常用的给回收。Lru近期最少使用算法1 package com.atguigu.beijingnews.utils; 2 3 import android.graphics.Bitmap; 4 5 import org.xutils.cache.LruCache; 6 7 /** 8 * 作用:Java之软引用&弱引用&虚引用 9 */10 public class MemoryCacheUtils {11 12 /**13 * 集合14 */15 private LruCachelruCache;16 17 public MemoryCacheUtils(){18 //使用了系统分配给应用程序的八分之一内存来作为缓存大小19 int maxSize = (int) (Runtime.getRuntime().maxMemory()/1024/8);20 lruCache = new LruCache (maxSize){21 @Override22 protected int sizeOf(String key, Bitmap value) {23 // return super.sizeOf(key, value);24 return (value.getRowBytes() * value.getHeight())/1024;25 }26 };27 }28 29 /**30 * 根据url从内存中获取图片31 * @param imageUrl32 * @return33 */34 public Bitmap getBitmapFromUrl(String imageUrl) {35 return lruCache.get(imageUrl);36 }37 38 /**39 * 根据url保存图片到lruCache集合中40 * @param imageUrl 图片路径41 * @param bitmap 图片42 */43 public void putBitmap(String imageUrl, Bitmap bitmap) {44 lruCache.put(imageUrl,bitmap);45 }46 }