高效展示图片LruCache

来源:互联网 发布:淘宝app分析 编辑:程序博客网 时间:2024/04/29 15:22

在android中展示图片过多就会出现内存溢出,为了能够高效的展示出图片这里就用缓存来处理。

首先我们写个缓存管理类ImageManager

import java.util.concurrent.Executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.content.Context;import android.graphics.Bitmap;import android.os.AsyncTask;import android.support.v4.util.LruCache;import android.util.Log;import android.widget.ImageView;import com.weather.forecast.R;//缓存管理类public class ImageManager {private Context context;private LruCache<String, Bitmap> mMemoryCache;private static ImageManager instance;private Executor mExecutor;private ImageManager() {}//单例public static ImageManager getInstance() {if (instance == null) {instance = new ImageManager();}return instance;}//应用程序初始化时调用public void init(Context context) {this.context = context;// 获取应用程序最大可用内存int maxMemory = (int) Runtime.getRuntime().maxMemory();// 设置图片缓存大小为程序最大可用内存的1/8int cacheSize = maxMemory / 8;mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getByteCount();}};mExecutor = Executors.newFixedThreadPool(3);}/** *  * @param url 传入路径 * @param image 图片控件 * @param Height 图片压缩的高 * @param Width 图片压缩的宽 * @param type 用来判断是本地照片还是资源文件中的图片(1是资源文件中的图片、2是本地图片) */public void loadImage(String url, ImageView image,int Height, int Width, int type) {image.setTag(url);Bitmap bm = mMemoryCache.get(url);if (bm != null) {image.setImageBitmap(bm);} else {//默认图image.setImageResource(R.drawable.default_image);//异步下载图片BitmapWorkerTask task = new BitmapWorkerTask(image);task.executeOnExecutor(mExecutor, url, Height, Width, type);}}/** * 异步下载图片的任务。 *  * @author guolin */class BitmapWorkerTask extends AsyncTask<Object, Void, Bitmap> {/** * 图片的URL地址 */private String imageUrl;private ImageView image;public BitmapWorkerTask(ImageView image) {super();this.image = image;}@SuppressWarnings("unused")@Overrideprotected Bitmap doInBackground(Object... params) {Bitmap bm = null;imageUrl = (String) params[0];Log.i("jjf", "imageUrl:" + imageUrl);int mHeight = (Integer) params[1];int mWidth = (Integer) params[2];int mType = (Integer) params[3];if (mType == 1) {//对资源图片进行压缩获得bitmapbm = DateUtil.BitmapResource(context, imageUrl, mWidth, mHeight);}else{//对本地图片进行压缩获得bitmapbm = DateUtil.getBitmapPath(imageUrl, mWidth, mHeight);}if (bm != null) {//进行存储(键值对形式)mMemoryCache.put(imageUrl, bm);}return bm;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);// 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。if (bitmap != null && imageUrl != null && image != null&& image.getTag().equals(imageUrl)) {image.setImageBitmap(bitmap);}}}}

程序初始化是调用如下:

public class GAPP extends Application {@Overridepublic void onCreate() {ImageManager.getInstance().init(getApplicationContext());}}

清单文件中注册

<application        android:name="yong.desk.weather.GAPP"        android:icon="@drawable/icon"        android:label="@string/app_name"        android:theme="@android:style/Theme.Holo.Light.NoActionBar" >        <activity

图片压缩类DateUtil

import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;public class DateUtil {public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {// 源图片的高度和宽度final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {// 计算出实际宽高和目标宽高的比率final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高// 一定都会大于等于目标的宽和高。inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;if (heightRatio == widthRatio) {inSampleSize = widthRatio;}}return inSampleSize;}// 资源文件的压缩public static Bitmap BitmapResource(Context context, String str,int reqWidth, int reqHeight) {// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小int resId = Integer.parseInt(str);final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(context.getResources(), resId, options);// 调用上面定义的方法计算inSampleSize值options.inSampleSize = calculateInSampleSize(options, reqWidth,reqHeight);// 使用获取到的inSampleSize值再次解析图片options.inJustDecodeBounds = false;return BitmapFactory.decodeResource(context.getResources(), resId,options);}// 本地文件的压缩public static Bitmap getBitmapPath(String str, int Width, int Height) {Bitmap mbitMap = null;BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;options.inDither = false;options.inPreferredConfig = Bitmap.Config.RGB_565;BitmapFactory.decodeFile(str, options);options.inSampleSize = calculateInSampleSize(options, Width, Height);options.inJustDecodeBounds = false;mbitMap = BitmapFactory.decodeFile(str, options);return mbitMap;}}

工具类都已经完成了,现在就在我们要使用的地方调用方法就ok了,下面是在gridview的适配器中调用。其他地方也是同样的使用

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {holder = new ViewHolder();convertView = inflater.inflate(R.layout.gridview_list_background_item, null);holder.imageName = (TextView) convertView.findViewById(R.id.gridview_lsit_item_textView);holder.image = (ImageView) convertView.findViewById(R.id.gridview_lsit_item_imageView);LayoutParams para = holder.image.getLayoutParams();para.height = Height;para.width = Width;holder.image.setLayoutParams(para);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}//判断本地文件路径是否为空if (!getImagePath(position).equals("")) {//判断本地文件是否存在if (FileUtil.isExist(getImagePath(position))) {//调用方法显示本地图片ImageManager.getInstance().loadImage(getImagePath(position), holder.image, Height, Width, 2);} else {//调用方法显示资源文件中的图ImageManager.getInstance().loadImage(Integer.toString(mImages[position]), holder.image, Height, Width, 1);}} else {//调用方法显示资源文件中的图ImageManager.getInstance().loadImage(Integer.toString(mImages[position]), holder.image, Height, Width, 1);}holder.imageName.setText(list[position]);return convertView;}






0 0