Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android利用LruCache為GridView加載大量本地圖片完整示例

Android利用LruCache為GridView加載大量本地圖片完整示例

編輯:關於Android編程

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 {
	private GridView mGridView;
	//圖片緩存類
	private LruCache 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(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如下:



   



gridview_item.xml如下:



    


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved