2

アプリの簡単なフォト ギャラリーに取り組んでいます。しかし、本当に厄介なメモリ リークが発生しており、その処理方法がわかりません。

皆さん、私を助けてくれますか? 他の質問で検索しましたが、回答によると、私は正しいことをしているようです。もちろん、そうではありません。

私のコード:

を使っTouchImageViewて画像を表示しています。

ViewPagerまた、次のようにズーム機能をサポートするように拡張しました。

public class ExtendedViewPager extends ViewPager {

    public ExtendedViewPager(Context context) {
        super(context);
    }

    public ExtendedViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if (v instanceof TouchImageView) {
            /*
            canScrollHorizontally is not supported for Api < 14. To get around this issue,
            ViewPager is extended and canScrollHorizontallyFroyo, a wrapper around
            canScrollHorizontally supporting Api >= 8, is called.
            */
            return ((TouchImageView) v).canScrollHorizontallyFroyo(-dx);
        } else {
            return super.canScroll(v, checkV, dx, x, y);
        }
    }
}

この写真の一部は大きい場合があります (たとえば、2000x2000px など)。ビューresampleに追加する前に、このリサンプル関数を使用します。

public static Bitmap resample(int resourceID, boolean toFullScreen, Context c){
        //set the width and height we want to use as maximum display
        WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        int targetWidth = display.getWidth();
        int targetHeight = display.getHeight();

        //create bitmap options to calculate and use sample size
        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();

        //first decode image dimensions only - not the image bitmap itself
        bmpOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(c.getResources(), resourceID, bmpOptions);

        //image width and height before sampling
        int currHeight = bmpOptions.outHeight;
        int currWidth = bmpOptions.outWidth;

        //variable to store new sample size
        int sampleSize = 1;

        //calculate the sample size if the existing size is larger than target size
        if (toFullScreen || currHeight > targetHeight || currWidth > targetWidth){
            //use either width or height
            if (toFullScreen || currWidth > currHeight)
                sampleSize = Math.round((float)currHeight / (float)targetHeight);
            else
                sampleSize = Math.round((float)currWidth / (float)targetWidth);
        }

        //use the new sample size
        bmpOptions.inSampleSize = sampleSize;
        //now decode the bitmap using sample options
        bmpOptions.inJustDecodeBounds = false;

        //get the file as a bitmap and return it
        Bitmap pic = BitmapFactory.decodeResource(c.getResources(), resourceID, bmpOptions);
        return pic;
    }

そして、私の実装でそれを呼び出します。ここでは、ビットマップPagerAdapterも試みます。recycle()

private class TouchImagePagerAdapter extends PagerAdapter {
    @Override
    public int getCount() {
        return galleryImages.length;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Context context = PhotoGalleryActivity.this;
        TouchImageView touchImageView = new TouchImageView(context);
        touchImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

        touchImageView.setImageBitmap(Helper.resample(galleryImages[position].getImgResource(), false, getApplicationContext()));
        container.addView(touchImageView, 0);

        return touchImageView;
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object object) {
        TouchImageView ti = (TouchImageView) object;
        BitmapDrawable bmpDrawable = (BitmapDrawable) ti.getDrawable();
        if (bmpDrawable != null) {
            Bitmap bmp = bmpDrawable.getBitmap();
            if(bmp != null && !bmp.isRecycled())
                bmp.recycle();
        }
        collection.removeView(ti);
        ti = null;
    }

    @Override
    public void destroyItem(View collection, int position, Object o) {
        View view = (View)o;
        ((ViewPager) collection).removeView(view);
        view = null;
    }
}

手がかりはありますか?前もって感謝します。

4

2 に答える 2

1

タグ内のプロジェクトのマニフェスト ファイルに次の行を追加します。

アンドロイド:ラージヒープ="true"

例:

   <application
    android:name="com......"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:theme="@style/CustomActionBarTheme">

これにより、アプリケーションが動作するためのメモリを増やすことができます

于 2015-05-18T05:00:13.483 に答える
1

元の bmp サイズが imageview より大きい場合は、inSampleSize 2 または 4 を変更することをお勧めします。2000x2000を超える画像が時々あるとおっしゃいました。メモリの問題が発生する可能性があります。

于 2015-05-18T02:09:27.347 に答える