分享一个轻量级图片加载类 ImageLoader

ImageLoader 这类的 图片加载网络上一大推,像比较出名的有nostra13 的-Image-Loader图片加载,xUtil的图片加载,还有 Facebook 的 Fresco 。很多,但本着求学的态度,最近在做项目时有图片加载这个需求就自己写了个轻量级的 (本地)图片缓存加载 功能,分享给各位。

里面涉及了 LruCache ,ExecutorService,处理大图的 BitmapFactory 原理,view.setTag() .

好了,不多说,先一步一步来:
首先看一下我封装的类怎么使用:

// 本地照片绝对路径 String imageUrl = (String) t; // 得到 ImageView ImageView grid_item = holder.getView(R.id.grid_item); // 设置 tag ,标记用的,反正图片显示错位 grid_item.setTag(imageUrl); /** * 显示 图片 * * @param context * : 上下文 * @param imageView * : ImageView 控件 * @param sourcePath * : 图片 地址 * @param r_Id * : 默认 图片 id ,R.drowable.id; * @param callback * :图片显示 回调 */ new ImageLoader().displayBmp(mContext,grid_item, imageUrl, R.drawable.img_bg,this);

是不是很简单。

接下来具体分析 ImageLoader 这个类:

都知道手机的内存有限,不可能将所有的图片都加进内存,所以android 提供了一个 LruCache 方法,用到的 算法 是 :近期最少使用算法 ,及在图片不断的加进缓存,最少使用的图片也在不断的移除缓存 ,从而避免的内存不够的问题。

LruCache 的初始化代码如下:

public ImageLoader() { // 取应用内存的 8/1 作为 图片缓存用 int cacheSize = maxMemory / 8; // 得到 LruCache mLruCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount(); } }; } /** * 将图片存储到LruCache */ public void putBitmapToLruCache(String key, Bitmap bitmap) { if (getBitmapFromLruCache(key) == null && mLruCache != null) { mLruCache.put(key, bitmap); } } /** * 从LruCache缓存获取图片 */ public Bitmap getBitmapFromLruCache(String key) { return mLruCache.get(key); }

LruCache 就像 HashMap 一样 利用put 和 get 得到缓存的东西。

接着看 图片的 具体加载,先把代码贴出来:

/** * 显示 图片 * * @param context * : 上下文 * @param imageView * : ImageView 控件 * @param sourcePath * : 图片 地址 * @param r_Id * : 默认 图片 id ,R.drowable.id; * @param callback * :图片显示 回调 */ public void displayBmp(final Context context, final ImageView imageView, final String sourcePath, final int r_Id, final ImageCallback callback) { final String path; if (!TextUtils.isEmpty(sourcePath)) { path = sourcePath; } else { return; } // 先 试着 从 缓存 得到 图片 , path 作为 图片的 key Bitmap bmp = mLruCache.get(path); if (bmp != null) { if (callback != null) { // 回调 图片 显示 callback.imageLoad(imageView, bmp, sourcePath); } // imageView.setImageBitmap(bmp); return; } // 如果 bmp == null ,给 imageView 显示默认图片 imageView.setImageResource(r_Id); // 启动 线程池 threadPoolUtils.getExecutorService().execute(new Runnable() { Bitmap bitmap = null; @Override public void run() { // TODO Auto-generated method stub try { // 加载 图片 地址 对应 的 缩略图 bitmap = revitionImageSize(imageView, sourcePath); } catch (Exception e) { } if (bitmap == null) { try { // 如果 缩略图 没加载成功 显示 默认 设置的图片 bitmap = BitmapFactory.decodeResource(context.getResources(), r_Id); } catch (Exception e) { } } if (path != null && bitmap != null) { // 将 缩略图 放进 缓存 , path 作为 key putBitmapToLruCache(path, bitmap); } if (callback != null) { handler.post(new Runnable() { @Override public void run() { // 回调 图片 显示 callback.imageLoad(imageView, bitmap, sourcePath); } }); } } }); }

代码不是狠多,主要就是 先从缓存加载图片,当加载图片为空时,再从手机的图片地址加载图片

bitmap = revitionImageSize(imageView, sourcePath);

加载缓存图片就不多说了,看的也明白, mLruCache.get(key);就这么简单

具体分析 revitionImageSize() 这个方法吧:

public Bitmap revitionImageSize(ImageView imageView, String path) throws IOException { // 得到 布局 ImageView 的 宽高 int img_width = imageView.getWidth(); int img_height = imageView.getHeight(); BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(path))); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); in.close(); int height = options.outHeight; int width = options.outWidth; Bitmap bitmap = null; int inSampleSize = 1; // 计算出实际宽高和目标宽高的比率 final int heightRatio = Math.round((float) height / (float) img_height); final int widthRatio = Math.round((float) width / (float) img_width); // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高 // 一定都会大于等于目标的宽和高。 inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; // 调用上面定义的方法计算inSampleSize值 options.inSampleSize = inSampleSize; options.inJustDecodeBounds = false; in = new BufferedInputStream(new FileInputStream(new File(path))); bitmap = BitmapFactory.decodeStream(in, null, options); in.close(); return bitmap; }

代码我也写了注释了 ,一般在加载图片时都有对图片一定的压缩处理避免OOM,所以上面的处理方法也是挺常见的,对要显示 图片 根据 imageview 控件大小进行一定的压缩。

如果对 图片压缩处理不是很理解的朋友这么我简单解释一下:

首先加载完图片:

BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(path)));

然后:

options.inJustDecodeBounds = true;

再接着:

int height = options.outHeight; int width = options.outWidth;

这时候注意 程序并没有把图片真正的加载进来,options.inJustDecodeBounds = true;

这句在起作用,但图片的宽和高 的信息我们却得到了,就可以处理压缩图片了!

压缩完图片再:

options.inJustDecodeBounds = false;

重新得到压缩后的图片:

bitmap = BitmapFactory.decodeStream(in, null, options);

解释完毕。

仔细看代码的同学会发现 displayBmp() 方法里面有个 回调参数:

回调接口如下:

/** * 显示图片回调 * * @author Administrator * */ public interface ImageCallback { public void imageLoad(ImageView imageView, Bitmap bitmap, Object... params); }

具体实现是在显示图片的地方回调的:

/** * 图片 缓存回调 */ @Override public void imageLoad(ImageView imageView, Bitmap bitmap, Object... params) { if (imageView != null && bitmap != null) { String url = (String) params[0]; // 判断 这里的 url 是否 对应 imageView.getTag() // 如果 将这句 判断 去掉 那么 就会出现 经常出现的 图片 显示 错位 问题 !!!! if (url != null && url.equals((String) imageView.getTag())) { ((ImageView) imageView).setImageBitmap(bitmap); } } }

代码注释的地方也写了,不太理解的同学可以私信交流,另外附上我 github github连接上的源码,可以下载下了运行方便好理解:

为了你方便使用,在你的项目中添加如下依赖即可:

dependencies { compile 'com.zts:imageloader:1.1.1' }

时间: 2024-09-16 18:18:49

分享一个轻量级图片加载类 ImageLoader的相关文章

分享一个轻量级图片加载类 ImageLoader_Android

ImageLoader 这类的 图片加载网络上一大推,像比较出名的有nostra13 的-Image-Loader图片加载,xUtil的图片加载,还有 Facebook 的 Fresco .很多,但本着求学的态度,最近在做项目时有图片加载这个需求就自己写了个轻量级的 (本地)图片缓存加载 功能,分享给各位. 里面涉及了 LruCache ,ExecutorService,处理大图的 BitmapFactory 原理,view.setTag() . 好了,不多说,先一步一步来: 首先看一下我封装的

Swift版本的图片加载类

之前使用OC版本的,都是基于AFN而自行封装的类库, 现在写了一个swift版本的,很方便使用,在些开源出来. 首先是图片下载类: // // HYBImageLoader.swift // OSChinaClient // // Created by 黄仪标 on 15/3/5. // Copyright (c) 2015年 huangyibiao free edu. All rights reserved. // import Foundation import UIKit /// ///

Android图片加载的缓存类_Android

本文为大家分享了Android图片加载的缓存类,供大家参考,具体内容如下 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReferenc

Android图片加载的缓存类

本文为大家分享了Android图片加载的缓存类,供大家参考,具体内容如下 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReferenc

设计简单的Android图片加载框架_Android

目前Android 发展至今优秀的图片加载框架太多,例如: Volley ,Picasso,Imageloader,Glide等等.但是作为程序猿,懂得其中的实现原理还是相当重要的,只有懂得才能更好地使用.于是乎,今天我就简单设计一个网络加载图片框架.主要就是熟悉图片的网络加载机制. 一般来说,一个优秀的 图片加载框架(ImageLoader) 应该具备如下功能: 图片压缩 内存缓存 磁盘缓存 图片的同步加载 图片的异步加载 网络拉取 那我们就从以上几个方面进行介绍: 1.图片压缩(有效的降低O

详解Android 教你打造高效的图片加载框架

1.概述 优秀的图片加载框架不要太多,什么UIL , Volley ,Picasso,Imageloader等等.但是作为一名合格的程序猿,必须懂其中的实现原理,于是乎,今天我就带大家一起来设计一个加载网络.本地的图片框架.有人可能会说,自己写会不会很渣,运行效率,内存溢出神马的.放心,我们拿demo说话,拼得就是速度,奏事这么任性. 关于加载本地图片,当然了,我手机图片比较少,7000来张: 1.首先肯定不能内存溢出,但是尼玛现在像素那么高,怎么才能保证呢?我相信利用LruCache统一管理你

设计简单的Android图片加载框架

目前Android 发展至今优秀的图片加载框架太多,例如: Volley ,Picasso,Imageloader,Glide等等.但是作为程序猿,懂得其中的实现原理还是相当重要的,只有懂得才能更好地使用.于是乎,今天我就简单设计一个网络加载图片框架.主要就是熟悉图片的网络加载机制. 一般来说,一个优秀的 图片加载框架(ImageLoader) 应该具备如下功能: 图片压缩 内存缓存 磁盘缓存 图片的同步加载 图片的异步加载 网络拉取 那我们就从以上几个方面进行介绍: 1.图片压缩(有效的降低O

php自动加载类

很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件.一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表. 在软件开发的系统中,不可能把所有的类都写在一个PHP文件中,当在一个PHP文件中需要调用另一个文件中声明的类时,就需要通过include把这个文件引入.不过有的时候,在文件众多的项目中,要一一将所需类的文件都include进来,是一个很让人头疼的事,所以我们能不能在用到什么类的时候,再把这个类所在的php文件导入呢?这就是我们这里我们要讲的

Visual Basic .NET 中动态加载类 (三)

visual|动态|加载 ··Microsoft 步骤 8:用新的窗体信息更新配置文件 现在,我们已经创建了一些新窗体,还需要在配置文件中引用它们.请用以下代码行替换 FormsOnTheFly.exe.config 中的占位符信息: <add key="First Form" value="C:\NewForms\FirstForm.dll~FirstForm.Form1"></add><add key="Second Fo