1

メモリの問題

そのため、上部に 640 x 480 の大きな画像が 1 つと、遅延読み込みされているギャラリーの一部である 3 つの画像がある詳細ビューをページングできるアプリを作成しています。Google のデザイン ガイドラインに従って、これが彼らの提案です。メモリ不足のためにクラッシュする前に、おそらく 12 ~ 13 個のフラグメントをページングできます。この問題にはいくつかの犯人がいると思います。

1.) FragmentStatePager を使用しています。これは、メモリが問題になったときに表示されていないフラグメントを破壊するべきではありませんか? これは起こっていません。自動だと思ってました。これを実現するにはどうすればよいですか? Fragment の実装方法と関係があるのでしょうか? アクティビティの設定はすべて onCreateView で行います。完全を期すために、このソースを含めました。プレーンバニラはこちら:

public static class MyAdapter extends FragmentStatePagerAdapter {


        public MyAdapter(FragmentManager fm) {
            super(fm);              
        }

        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        @Override
        public Fragment getItem(int position) {
            return InventoryDetailFragment.newInstance(position);
        }
    }

2.) メモリに配置せずに、ダウンロードする必要があるイメージのサイズを把握しようとする方法があります。次に、画像をダウンロードしながら必要なサイズに圧縮します。これはうまく実装されていません。しかし、何がうまくいかないのかわかりません。

private Bitmap downloadBitmap(String url, int width, int height) {
    Bitmap bitmap = null;
    int scale = 1;
    try {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;  
        bitmap = BitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, options);

        if (options.outHeight > height || options.outWidth > width) {
            scale = (int) Math.max(((options.outHeight)/ height), ((options.outWidth)/ width));             }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        bitmap = BitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, o2); 
        cache.put(url, new SoftReference<Bitmap>(bitmap));


    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Error e){
        Log.d("TEST", "Garbage Collector called!");
        System.gc();
    }
    return bitmap;
}

やり方を知っていることはすべて試しましたが、Android/Java についての私の貧弱な理解を超えています。助けてください!ありがとう!

4

2 に答える 2

1

変更する必要があることがいくつかあります。

  1. これは恐ろしい考えBitmapFactory.decodeStream((InputStream)new URL (url).getContent(), null, options);です。これが実行されるたびに、Web から画像を取得しています (投稿したコードでは2 回)。代わりに、イメージをダウンロードしてローカルにキャッシュする必要があります。

  2. recycle()フラグメントがデタッチされるとすぐにビットマップを呼び出すロジックをフラグメントに追加します。フラグメントがアタッチされるたびに (キャッシュから) イメージを常にリロードするロジックを追加します。

  3. 最後に、あなたのinSampleSize計算は間違っています。inSampleSize1,2,4,8 のように、2 のべき乗の値を指定する必要があります。対数または単純なバイナリ ロジックを使用して正しいものを取得できます。これは私が使用するもので、常に少なくとも 2 を使用してダウンサンプリングします (画像が大きすぎることがわかっている場合にのみこれを呼び出します)。

-

int ratio =  (int) Math.max((height/options.outHeight), ( width/options.outWidth); //notice that they're flipped     
  for (int powerOfTwo = 64; powerOfTwo >=2; powerOfTwo = powerOfTwo >> 1 ) { //find the biggest power of two that represents the ratio
    if ((ratio & powerOfTwo) > 0) {
      return powerOfTwo;
    }
  }
于 2012-04-04T14:20:54.893 に答える
0

グラフィックスを opengl で認識している場合、これはメモリにカウントされません。別のオプションは使用することです

android:largeHeap="true"

マニフェストで。働いている可能性があります。

ddvm を使用してメモリ リークを検索しましたか?

http://www.youtube.com/watch?v=_CruQY55HOk

于 2012-04-04T14:16:55.913 に答える