1

これが私のコードです:

int[] image = {R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
        R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
        R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
        R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
        R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
        R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2};

そして getView:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
        imageView.setBackgroundResource(image[position]);

        return convertView;
    }

すべて順調。OOM なし。

次に、最初にドローアブルをサンプリングします。

public static Bitmap sampleImage(Context context, int resourceId, int sampleSize) {        
            Bitmap resizeBmp = null;
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inSampleSize = sampleSize;
            resizeBmp = BitmapFactory.decodeResource(context.getResources(), resourceId, opts);

            return resizeBmp;
        }

そして新しい getView:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
        Bitmap item = BitmapUtil.sampleMaskInShelf(getApplicationContext(), image[position], 4);
        imageView.setImageBitmap(item);
        //      imageView.setBackgroundResource(image[position]);

        return convertView;
    }  

事は起こった。最初は、アプリケーションはクラッシュしません。しかし、使用メモリが 50MB を超えているため、上下にスクロールすると OOM が発生します。

質問は次のとおりです。1)画像をサンプリングすると、使用されるメモリが増加する理由。2) メモリ使用量を減らす方法、他に方法はありますか?

4

4 に答える 4

5

ここでListViewを扱っているようですか?

その場合、いくつかの手順を実行すると、より良いサービスが提供されます (そして、うまくいけば、かなりの量のメモリを節約できます)。

  1. convertView可能な限りを再利用したいと考えています。これを行う方法については、多くの記事が書かれています。 これが1つです。
  2. 実際には 2 つの異なる画像 (image1image2) しかないようです。また、呼び出されるたびにビットマップをサンプリングしているようですgetView()。おそらく、サンプリングされた 2 つのビットマップを事前に計算し、それらを繰り返し使用する必要があります。
于 2012-09-26T01:42:44.213 に答える
2

この正確な問題をカバーする 3 つの優れた Android トレーニング記事があります。

  1. 大きなビットマップを効率的にロードする
  2. ビットマップのキャッシュ
  3. ビットマップの表示(具体的には GridView を使用)

これら 3 つすべてを読んで、どのような手法が使用されているかを理解し、すべてのトレーニング コードを 1 つの例にカプセル化したサンプル アプリケーションをダウンロードしてみてください。あなたの場合、画像を表示サイズまで事前にサンプリングしてから、LruCacheを使用するだけで十分だと思います。

于 2012-09-30T20:31:07.293 に答える
0

ガベージコレクターはビットマップの割り当て解除を自動的に処理しないため、ビットマップを変数に直接割り当てるときはいつでも、それが終わったらbitmap.recycle()も呼び出す必要があります。そうしないと、メモリリークが発生します。これはあなたが持っているものです。ただし、ビットマップをドローアブルに割り当ててから、bitmap.recycle()を呼び出してからドローアブルを使用しようとすると、ドローアブルはリサイクルされたビットマップにアクセスできないため、例外が発生します。

私はあなたが持っているものと同様のListViewを書いていました、そして私がやったことは現在のビューポートより10スロット以上上のビットマップでbitmap.recycleを呼び出し、そのビットマップが持っていることを示すためにそのListViewアイテムにフラグを設定することでしたリサイクルされ、ユーザーがそこまでスクロールして戻った場合、getViewにビットマップを再ロードさせます。

于 2012-10-02T17:32:10.157 に答える
0

毎回新しいビューを作成する代わりに、..のようなビューを再利用するようにしてください。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if(v == null)  {   
        v=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
    } 
    ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
    imageView.setBackgroundResource(image[position]);

    return v;
}

OOM でさらに操作を行うには、以下のリンクを参照してください。 http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

または UniversalImage Loader Library を使用して画像をロードできます..そのライブラリはUniversalImageLoaderから見つけることができます

この助けを願っています...

于 2012-10-04T12:41:32.137 に答える