画像ギャラリーを実装しようとしています。これには、〜5〜15個の小さい画像と「現在選択されている」1つの大きい画像が表示されます。
次のようになります: http://www.mobisoftinfotech.com/blog/wp-content/uploads/2012/06/galleryDemo.png
多くの情報源を調べた結果、ビットマップ キャッシュ (lru-cache) を使用することにしました (このフォーラムのユーザーに感謝します!)。
現時点ではメモリリークは発生していませんが、スクロールするたびに一部の画像がキャッシュから削除され、それらをリロードする必要があるため、このソリューションには満足していません...ユーザーは画像をリロードしています...反対側にスクロールするたびに0.5〜1秒待つのは本当に面倒です...
public static WeakReference<Bitmap> getBitmap(String imageName, int width,
int height) {
if (!imageName.contains(".jpg")){
imageName += ".jpg";
}
String pathToImage = getPathToImage(imageName);
Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathToImage, options);
/*
* Calculate inSampleSize
*/
options.inSampleSize = calculateInSampleSize(options, width, height);
/*
* Removes the alpha-channel from bitmap (not necessary)
*/
options.inPreferredConfig = Bitmap.Config.RGB_565;
/*
* Decode bitmap with inSampleSize set
*/
options.inJustDecodeBounds = false;
WeakReference<Bitmap> scaledBitmap = new WeakReference<Bitmap>(
BitmapFactory.decodeFile(pathToImage, options));
return scaledBitmap;
画像の取得を間違える可能性はありますか? 現時点では、単一選択の画像には 320x480 の解像度を使用し、下部のリストには 64x64 の解像度を使用します...
本当に奇妙なのは、画像の解像度がどれほど大きいかは問題ではないという事実です.64x64画像のみを選択しても、lru-cacheはいくつかの画像を削除します... lruキャッシュ?
次のコードは私の実装を示しています。
/*
* Bitmaps which should be shown
*/
mMemoryCache = (BitmapCache) getLastNonConfigurationInstance();
if (mMemoryCache == null) {
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/4th of the available memory for this memory cache.
final int cacheSize = maxMemory / 2; // TODO default 8
mMemoryCache = new BitmapCache(cacheSize);
}
クラス BitmapCache:
public BitmapCache(int maxSize, Resources resources) {
super(maxSize);
this.resources = resources;
}
@Override
protected int sizeOf(String key, AsyncDrawable value) {
if (value.getBitmap() != null) {
/*
* The cache size will be measured in kilobytes rather than
* number of items.
*/
return value.getBitmap().getRowBytes()
* value.getBitmap().getHeight() / 1024;
}
return super.sizeOf(key, value);
}
public void loadBitmap(Picture picture, ImageView mImageView,
ImageResolution resolution) {
if (cancelPotentialWork(picture.getFileName(), // + resolution.name()
mImageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(this,
mImageView, picture, resolution);
final AsyncDrawable asyncDrawable = new AsyncDrawable(resources,
null, task);
mImageView.setImageDrawable(asyncDrawable);
task.execute();
}
}
どうもありがとうございました :(
いくつかのコード: BitmapWorkerTask:
@Override
protected Bitmap doInBackground(Void... params) {
/*
* Decode image in background.
*/
final Bitmap bitmap = FileHandler.getBitmap(
picture.getPictureId() + "", resolution).get();
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
/*
* Once complete, see if ImageView is still around and set bitmap.
*/
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
final BitmapWorkerTask bitmapWorkerTask = asyncDrawable
.getBitmapWorkerTask();
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
bitmapCache.addBitmapToMemoryCache(
picture.getFileName(), // + resolution.name()
asyncDrawable);
}
}
}
}
}