int memory = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

int memClass = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

としたとき
memClass * 1024 * 1024 が最大メモリ量となる。
フォトスタンドでは
memClass * 1024 * 1024 / 2 のメモリをメモリキャッシュとしている・

メモリキャッシュのクラスはSoftReferenceやWeakReferenceではなく
LruCacheクラスを使うことが推奨されている。
SoftReferenceやWeakReferenceはメモリがクリアされやすい。

LruCacheは通常のandroid.jarには用意されていないため、
supportV4をダウンロード(http://developer.android.com/tools/extras/support-library.html)
してパスをつないでください。

オリジナルキャッシュクラスの作成例

public final class ImageCache {
// このデバイスのメモリクラスをゲットする。
// この量を超えるとOutOfMemory例外が投げられる。
final static int memClass = Common.getMemClass();
private static final int MEM_CACHE_SIZE = memClass * 1024 * 1024 / 2; // 1MB
private static LruCache sLruCache;
//コンストラクタ
private ImageCache() {
}
//キャッシュ作成
static {
sLruCache = new LruCache(MEM_CACHE_SIZE) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
//画像をキャッシュに保持
public static void setImage(String key, Bitmap bitmap) {
if (getImage(key) == null) {
sLruCache.put(key, bitmap);
}
}
//キャッシュから画像を取得
public static Bitmap getImage(String key) {
return sLruCache.get(key);
}
}

・AsyncTask——————————————————————–
画像を描画するときはメインThreadを使わず、backgroundで処理する

・GridViewやListViewで画像がずれる。——————————————————————–
imageviewにtagをつける。画像のファイル名もしくはパス名など

・スクロール中は読み込み実行しない——————————————————————–
GridViewにScrollのリスナーセット
スクロール中はmBusy=true
getViewでmBusyのときはAsyncTaskを実行しない

gridView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView paramAbsListView, int scrollState) {
Logger.e(“scroll end”);
switch (scrollState) {
// スクロールしていない
case OnScrollListener.SCROLL_STATE_IDLE:
// スクロール中であることを示すフラグをfalseに
if(mBusy){
Logger.e(“scroll end”);
//GridViewにsetSelectionFromTopはない
mImageAdapter.notifyDataSetChanged();
}
mBusy = false;
break;
// スクロール中
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
Logger.e(“SCROLL_STATE_TOUCH_SCROLL”);
mBusy = true;
break;
// はじいたとき
case OnScrollListener.SCROLL_STATE_FLING:
Logger.e(“SCROLL_STATE_TOUCH_SCROLL”);
mBusy = true;
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});

・一度読み込んだものは再読み込みしない———————————————–
//キャッシュを調べる
Bitmap image = ImageCache.getImage(f.getPath());
if(image==null){
 //画像なし
}else{
 //あり
if(タグチェック)
  imageView.setImageBitmap(image);
}

・画像を粗くする——————————————————————–
inJustDecodeBoundsをtrueにしてサイズだけ読み取り
縮尺値を決めて、inJustDecodeBoundsをfalseにして画像を読み込む

//読み込み用のオプションオブジェクトを生成
BitmapFactory.Options options = new BitmapFactory.Options();
//この値をtrueにすると実際には画像を読み込まず、
//画像のサイズ情報だけを取得することができます。
options.inJustDecodeBounds = true;

//画像ファイル読み込み
//ここでは上記のオプションがtrueのため実際の
//画像は読み込まれないです。
BitmapFactory.decodeFile(path, options);

//読み込んだサイズはoptions.outWidthとoptions.outHeightに
//格納されるので、その値から読み込む際の縮尺を計算します。
//このサンプルではどんな大きさの画像でもHVGAに収まるサイズを
//計算しています。
int scaleW = options.outWidth / 380 + 1;
int scaleH = options.outHeight / 420 + 1;

//縮尺は整数値で、2なら画像の縦横のピクセル数を1/2にしたサイズ。
//3なら1/3にしたサイズで読み込まれます。
int scale = Math.max(scaleW, scaleH);

//今度は画像を読み込みたいのでfalseを指定
options.inJustDecodeBounds = false;

//先程計算した縮尺値を指定
options.inSampleSize = scale;

//これで指定した縮尺で画像を読み込めます。
//もちろん容量も小さくなるので扱いやすいです。
Bitmap image = BitmapFactory.decodeFile(path, options);