ImageLoader
来源:互联网 发布:sql select as table 编辑:程序博客网 时间:2024/06/06 15:44
ImageLoader
代码来源于android艺术开发探索 12章,主要为了减少加载图片的资源损耗,利用了下面2个知识点
1 LruCache and DiskLruCache两个缓冲
其中LruCache相当于一级缓存 , DiskLruCache相当于二级缓存,从LruCache中读取图片的速度最快,接下来是 DiskLruCache ,最慢就是从web服务器获取 , 所以在第一次我们会把数据网上下载下来后缓存到Disk和Memory中,下次的读取速度就会很快,注意的是在主线上可以进行LruCache操作,但是不建议这样进行 , DiskLruCache操作只能在后台线程执行
2 bitmap sacle缩放减少内存消耗
下面分析代码
博主git源代码: https://git.oschina.net/qianlilo/ImageLoader_util.git
Bitmap缩放
#为什么要缩放哪? android给每个应用程序的内存是固定的 ,64M ,内存是宝贵的资源, # 但是,一张图片长和宽都扩大到2倍,内存要扩大到4倍,但是由于人眼的限制或者显示器的限制,增加分辨率效果并不明显,所以我们要使用合适的分辨率 /** * get bitmap from resourceId * @param resId resource Id * @param reqWidth require width * @param reqHeight require height * */ public Bitmap decodeSampleBitmapFromResource(Resources res, int resId , int reqWidth , int reqHeight){ final BitmapFactory.Options options = new BitmapFactory.Options(); //only get pic size , in this do not consume real data options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res , resId , options); options.inSampleSize = calculateInSampleSize(options , reqWidth , reqHeight); //can get real data from pic options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res , resId , options); } /** * calculate shrink resolution * @return more than 1 * @param options pic info * @param reqHeight require height * @param reqWidth require width * */ private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { //judge argment if(reqHeight == 0 || reqWidth == 0){ return 1; } final int height = options.outHeight; final int width = options.outWidth; Log.d(TAG, "origin pic { w = " +width + ", h = "+height+" } "); int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ( (halfHeight/inSampleSize) >= reqHeight && (halfWidth/inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
线程池的使用
#在这里使用线程池是因为每个图片都会去执行一个一次,开启多线程可以减少重复开启线程的资源开销 private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXNUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final long KEEP_ALIVE = 10L; private static final ThreadFactory sThreadFacory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); @Override public Thread newThread(@NonNull Runnable r) { return new Thread(r , "ImageLoader#"+mCount.getAndIncrement()); } }; public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor( CORE_POOL_SIZE , MAXNUM_POOL_SIZE , KEEP_ALIVE , TimeUnit.SECONDS , new LinkedBlockingQueue<Runnable>() , sThreadFacory);
LruChache的使用
#由于lrucache是官方的,我们可以直接使用 #我们选取一个应用程序最大可以内存的1/8位缓存 int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); int cacheSize = maxMemory/8; LruCache mMemoryCache = new LruCache<String, Bitmap>(cacheSize){ @Override #计算每张图片的大小 , 根据代码是这个意思 protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } }; /** * add bitmap to memory cache 缓存到内存 * */ private void addBitmapToMemoryCache(String key,Bitmap bitmap){ if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key , bitmap); } } /** * get bitmap from memory cache 从内存得到缓存 * */ private Bitmap getBitmapFromMemCache(String key){ return mMemoryCache.get(key); } #可以发现不管是存还是取都很简单 , 书的作者这里使用了URl通过MD5得到key #个人观点觉得在这里是有信息熵没什么必要,本来的URL就是明文,关于加密简单使用可以看我的另一个博客 # [这里写链接内容](http://blog.csdn.net/chenqianleo/article/details/76736575%20java%20%E4%BF%A1%E6%81%AF%E7%86%B5%20%E5%8A%A0%E5%AF%86) private String hashKeyFromUrl(String url){ String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(url.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(url.hashCode()); e.printStackTrace(); } return cacheKey; } private String bytesToHexString(byte[] bytes){ StringBuilder sb = new StringBuilder(); int len = bytes.length; for (int i=0;i<len;i++){ String hex = Integer.toHexString(0xFF & bytes[i]); if(hex.length() == 1){ sb.append('0'); } sb.append(hex); } return sb.toString(); }
DiskLruCache
#不是官方的,但是官方推荐这样使用,所以我们要直接拷贝一个DiskLruCache.java文件到项目,具体的可以上网或者下载源码来得到 DiskLruCache mDiskLruCache = DiskLruCache.open(diskCacheDir , 1 , 1 , DISKC_CACHE_SIZE); #存 ,这里是先通过网络下载在缓存得到diskcache private Bitmap loadBitmapFromHttp(String uri, int reqWidth, int reqHeight) throws IOException { #在UI线程不可以使用网络耗时操作 if(Looper.myLooper() == Looper.getMainLooper()){ throw new RuntimeException("can not visit netWork from UI thread"); } if(mDiskLruCache == null){ return null; } String key = hashKeyFromUrl(uri); #开始存 DiskLruCache.Editor editor = mDiskLruCache.edit(key); if (editor != null) { OutputStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX); //这个函数是把url的内容存到outputstream中去 if (downloadUrlToStream(uri, outputStream)) { editor.commit(); } else { editor.abort(); } mDiskLruCache.flush(); } return loadBitmapFromDiskCache(uri , reqWidth , reqHeight); } #取 private Bitmap loadBitmapFromDiskCache(String uri, int reqWidth, int reqHeight) throws IOException { if(Looper.myLooper() == Looper.getMainLooper()){ Log.e(TAG, " load bitmap from UI thread, not recommended" ); } if(mDiskLruCache == null){ return null; } Bitmap bitmap = null; String key = hashKeyFromUrl(uri); DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); if(snapshot != null){ FileInputStream fileInputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); FileDescriptor fileDescriptor = fileInputStream.getFD(); #自己实现的,使用了上面介绍的缩放 bitmap = mImageResizer.decodeSampleBitmapFromFileDescriptor(fileDescriptor , reqWidth , reqHeight); # 内存缓存中没有 , 缓存到内存中去 if(bitmap != null){ addBitmapToMemoryCache(key , bitmap); } } return bitmap; }
完整的代码实现了照片墙的功能,可以下载代码看完整demo
阅读全文
0 0
- ImageLoader
- ImageLoader
- ImageLoader
- ImageLoader
- ImageLoader
- imageloader
- ImageLoader
- ImageLoader
- imageLoader
- ImageLoader
- ImageLoader
- ImageLoader
- ImageLoader
- ImageLoader
- imageloader
- ImageLoader
- ImageLoader
- ImageLoader
- maven多实例打包
- c语言实现扫雷(非图形化界面)
- Centos7 Zookeeper安装笔记
- 观察者模式
- 俩个有序链表的合并
- ImageLoader
- sql
- 赫夫曼树以及赫夫曼编码
- 514. Freedom Trail
- 文件上传—jspSmartUpload组件
- linux命令行下软件的安装等操作-软件包管理
- USACO-Section2.1 The Castle[bfs]
- [Microsoft] O(1) Check Power of 2
- C# 接收post到后台的json数据