利用LruCache为GridView加载大量本地图片完整示例

MainActivity如下:

package cc.testlrucache;

import android.os.Bundle;
import android.widget.GridView;
import android.app.Activity;
/**
 * Demo描述:
 * Android利用LruCache为GridView加载大量本地图片完整示例,防止OOM
 *
 * 更多参考:
 * http://blog.csdn.net/lfdfhl
 */
public class MainActivity extends Activity {
	private GridView mGridView;
	private GridViewAdapter mGridViewAdapter;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		init();
	}

	private void init(){
		mGridView = (GridView) findViewById(R.id.gridView);
		mGridViewAdapter = new GridViewAdapter(this, 0, ImagesPath.IMAGES_PATH, mGridView);
		mGridView.setAdapter(mGridViewAdapter);
	}

}

GridViewAdapter如下:

package cc.testlrucache;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.AbsListView.OnScrollListener;
/**
 *   LruCache的流程分析:
 *
 *   从第一次进入应用的情况下开始
 * 1 依据图片的Path从LruCache缓存中取图片.
 *   若图片存在缓存中,则显示该图片;否则显示默认图片
 * 2 因为是第一次进入该界面所以会执行:
 *   loadBitmaps(firstVisibleItem, visibleItemCount);
 *
 *   从loadBitmaps()方法作为切入点,继续往下梳理
 *
 * 3 尝试从LruCache缓存中取图片.如果在显示即可,否则进入4
 * 4 从SDCrad读取图片,并且将读取后的图片保存到LruCache缓存中
 *
 * 5 在停止滑动时,会调用loadBitmaps(firstVisibleItem, visibleItemCount)
 *   显示目前GridView可见Item的图片
 */
public class GridViewAdapter extends ArrayAdapter<String> {
	private GridView mGridView;
	//图片缓存类
	private LruCache<String, Bitmap> mLruCache;
	//GridView中可见的第一张图片的下标
	private int mFirstVisibleItem;
	//GridView中可见的图片的数量
	private int mVisibleItemCount;
	//记录是否是第一次进入该界面
	private boolean isFirstEnterThisActivity = true;

	public GridViewAdapter(Context context, int textViewResourceId,String[] objects, GridView gridView) {
		super(context, textViewResourceId, objects);
		mGridView = gridView;
		mGridView.setOnScrollListener(new ScrollListenerImpl());
		//应用程序最大可用内存
		int maxMemory = (int) Runtime.getRuntime().maxMemory();
		//设置图片缓存大小为maxMemory的1/3
		int cacheSize = maxMemory/3;

		mLruCache = new LruCache<String, Bitmap>(cacheSize) {
			@Override
			protected int sizeOf(String key, Bitmap bitmap) {
				return bitmap.getRowBytes() * bitmap.getHeight();
			}
		};

	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		String path = getItem(position);
		View view;
		if (convertView == null) {
			view = LayoutInflater.from(getContext()).inflate(R.layout.gridview_item, null);
		} else {
			view = convertView;
		}
		ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
		//为该ImageView设置一个Tag,防止图片错位
		imageView.setTag(path);
		//为该ImageView设置显示的图片
		setImageForImageView(path, imageView);
		return view;
	}

	/**
	 * 为ImageView设置图片(Image)
	 * 1 从缓存中获取图片
	 * 2 若图片不在缓存中则为其设置默认图片
	 */
	private void setImageForImageView(String imagePath, ImageView imageView) {
		Bitmap bitmap = getBitmapFromLruCache(imagePath);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		} else {
			imageView.setImageResource(R.drawable.default_image);
		}
	}

	/**
	 * 将图片存储到LruCache
	 */
	public void addBitmapToLruCache(String key, Bitmap bitmap) {
		if (getBitmapFromLruCache(key) == null) {
			mLruCache.put(key, bitmap);
		}
	}

	/**
	 * 从LruCache缓存获取图片
	 */
	public Bitmap getBitmapFromLruCache(String key) {
		return mLruCache.get(key);
	}

   /**
    * 为GridView的item加载图片
    * @param firstVisibleItem GridView中可见的第一张图片的下标
    * @param visibleItemCount GridView中可见的图片的数量
    */
	private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
		try {
			for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
				String imagePath = ImagesPath.IMAGES_PATH[i];
				Bitmap bitmap = getBitmapFromLruCache(imagePath);
				if (bitmap == null) {
					System.out.println("--->XXXXX 图片"+imagePath+"不在缓存中"+",所以从SDCard读取");
					bitmap=BitmapFactory.decodeFile(imagePath);
					ImageView imageView = (ImageView) mGridView.findViewWithTag(imagePath);
					if (imageView != null && bitmap != null) {
						imageView.setImageBitmap(bitmap);
					}
					//将从SDCard读取的图片添加到LruCache中
					addBitmapToLruCache(imagePath, bitmap);
				} else {
					System.out.println("--->OOOOO 图片在缓存中="+imagePath+",从缓存中取出即可");
					//依据Tag找到对应的ImageView显示图片
					ImageView imageView = (ImageView) mGridView.findViewWithTag(imagePath);
					if (imageView != null && bitmap != null) {
						imageView.setImageBitmap(bitmap);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private class ScrollListenerImpl implements OnScrollListener{
	    /**
	     * 通过onScrollStateChanged获知:每次GridView停止滑动时加载图片
	     * 但是存在一个特殊情况:
	     * 当第一次入应用的时候,此时并没有滑动屏幕的操作即不会调用onScrollStateChanged,但应该加载图片.
	     * 所以在此处做一个特殊的处理.
	     * 即代码:
	     * if (isFirstEnterThisActivity && visibleItemCount > 0) {
	     *      loadBitmaps(firstVisibleItem, visibleItemCount);
	     *      isFirstEnterThisActivity = false;
	     *    }
	     *
	     * ------------------------------------------------------------
	     *
	     * 其余的都是正常情况.
	     * 所以我们需要不断保存:firstVisibleItem和visibleItemCount
	     * 从而便于中在onScrollStateChanged()判断当停止滑动时加载图片
	     *
	     */
		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
			mFirstVisibleItem = firstVisibleItem;
			mVisibleItemCount = visibleItemCount;
			if (isFirstEnterThisActivity && visibleItemCount > 0) {
				System.out.println("---> 第一次进入该界面");
				loadBitmaps(firstVisibleItem, visibleItemCount);
				isFirstEnterThisActivity = false;
			}
		}

		/**
		 *  GridView停止滑动时下载图片
		 *  其余情况下取消所有正在下载或者等待下载的任务
		 */
		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			if (scrollState == SCROLL_STATE_IDLE) {
				System.out.println("---> GridView停止滑动  mFirstVisibleItem="+mFirstVisibleItem+",mVisibleItemCount="+mVisibleItemCount);
				loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
			}
		}
	}
}

ImagesPath如下:

package cc.testlrucache;

public class ImagesPath {

	public final static String DIR="/mnt/sdcard/Test/";
	public final static String[] IMAGES_PATH = new String[] {
		DIR+"a.jpg",
		DIR+"b.jpg",
		DIR+"c.jpg",
		DIR+"d.jpg",
		DIR+"e.jpg",
		DIR+"f.jpg",
		DIR+"g.jpg",
		DIR+"h.jpg",
		DIR+"i.jpg",
		DIR+"j.jpg",
		DIR+"k.jpg",
		DIR+"l.jpg",
		DIR+"m.jpg",
		DIR+"n.jpg",
		DIR+"o.jpg",
		DIR+"p.jpg",
		DIR+"q.jpg",
		DIR+"r.jpg",
		DIR+"s.jpg",
		DIR+"t.jpg",
		DIR+"w.jpg",
		DIR+"x.jpg",
		DIR+"y.jpg",
		DIR+"z.jpg",
		DIR+"za.jpg",
		DIR+"zb.jpg",
		DIR+"zc.jpg",
		DIR+"zd.jpg",
		DIR+"ze.jpg",
		DIR+"zf.jpg",
		DIR+"zg.jpg",
		DIR+"zh.jpg",
		DIR+"zi.jpg",
		DIR+"zj.jpg",
		DIR+"zk.jpg",
		DIR+"zl.jpg",
		DIR+"zm.jpg"
};
}

 

main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

   <GridView
       android:id="@+id/gridView"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:verticalSpacing="10dip"
       android:listSelector="@android:color/transparent"
       android:numColumns="3"
    />

</RelativeLayout>

gridview_item.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="90dip"
        android:layout_height="90dip"
        android:src="@drawable/default_image"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

 

时间: 2024-11-01 04:50:49

利用LruCache为GridView加载大量本地图片完整示例的相关文章

利用LruCache和DiskLruCache加载网络图片实现图片瀑布流效果(升级版)

MainActivity如下: package cc.patience7; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 在原本的的基础上添加了本地缓存DiskLruCache * * 所以在该示例中对于图片的缓存采用了:LruCache + DiskLruCache 的技术 * * 参考

ios-IOS 加载大量本地图片内存暴增

问题描述 IOS 加载大量本地图片内存暴增 在做浏览本地图片的时候,有大量的本地图片需要加载,初始化的时候就用循环的方式 把所有的图片都加载出来导致内存暴增.该怎么改进.最好有代码~ 解决方案 你的图片应该是以瀑布流的方式显示的把?用户看到的只有当前展示的图片,其他图片可以稍候再加载到内存中,你可以建立一个图片队列,设置上限数为30,即内存中最多存在30张图片 你如果不想自己写,可以使用 SDWebImage 来做,它的缓存机制做得比较全面 解决方案二: iOS 加载图片时的内存警告 解决方案三

利用LruCache加载网络图片实现图片瀑布流效果(基础版)

PS: 2015年1月20日21:37:27 关于LoadImageAsyncTask和checkAllImageViewVisibility可能有点小bug 修改后的代码请参见升级版本的代码 http://blog.csdn.net/lfdfhl/article/details/42925193 MainActivity如下: package cc.patience3; import android.os.Bundle; import android.app.Activity; /** * D

利用LruCache加载网络图片实现图片瀑布流效果(改进版)

PS: 2015年1月20日21:37:27 关于LoadImageAsyncTask和checkAllImageViewVisibility可能有点小bug 修改后的代码请参见升级版本的代码 http://blog.csdn.net/lfdfhl/article/details/42925193 MainActivity如下: package cc.patience4; import cc.patience4.R; import android.os.Bundle; import androi

读取本地图片多选问题-很棘手的问题,关于gridview加载图片

问题描述 很棘手的问题,关于gridview加载图片 1. * 我的问题是用画布标记已经选中的图片,选中之后如果不重用view被选中的状态划过去再划过来是存在的,如果重用的话就会内存溢出,下面是我的代码,请哪位大帮忙看一看. package com.yonyou.uap.um.control.image; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util

存储-Gridview加载绑定数据源

问题描述 Gridview加载绑定数据源 Gridview加载绑定数据源利用的存储程序,执行大约需要10秒钟,怎么实现加载完成前提示"正在查询数据" 解决方案 http://www.cnblogs.com/linyijia/p/3542787.html 解决方案二: Gridview好像自带了这种滚动条控件吧!不然VS也有一个现成的滚动条控件

tomcat集群-nginx 反向代理三个本地tomcat 负载均衡配置 无法加载js css 图片等 也不报错

问题描述 nginx 反向代理三个本地tomcat 负载均衡配置 无法加载js css 图片等 也不报错 打开速度非常慢,到最后js css无法加载是什么问题 我的项目是ssh+jquery+easyui的 单独访问tomcat完全正常 访问nginx就这样了 .求大神指点啊 访问webapp根目录是可以的 我的页面都是在web-inf目录下的貌似不行 nginx配置如下: #user nobody; worker_processes 1; #error_log logs/error.log;

listview中嵌套gridview加载网络图片

问题描述 listview中嵌套gridview加载网络图片 我自己定义了一个ImageAdapter .public class ImageAdapter extends BaseAdapter {...(省略)@Overridepublic View getView(int position View convertView ViewGroup parent) {final ImageView imageView;if (convertView == null) {convertView =

Android的GridView加载的数据很多但是不会有下拉

问题描述 Android的GridView加载的数据很多但是不会有下拉 这是个课程表,我想他加载的数据可以自己有自己的位置,像表格一样,可以下拉下去查看得到,现在这个字都放一起来,不会处理,求大神! 解决方案 Android GridView 分页加载数据 解决方案二: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0918/1693.html