1

画像ギャラリーを実装しようとしています。これには、〜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);
                }
            }
        }
    }
}
4

1 に答える 1

0

驚くばかり!なぜうまくいかなかったのか、間違いを見つけました。障害は、AsyncDrawablesを格納している私のLruCacheにありましたが、これはまったく馬鹿げています。LruCacheのsizeOfが呼び出されるたびに、非同期描画可能ファイル内のビットマップはnullであったため、彼はsuper.sizeOf(key、value)を返しました。

今ではチャームのように機能します!! :)

あなたの助けをありがとう!

于 2013-02-09T20:50:47.130 に答える