21

私はViewPagerに12のビューを表示するゲームブックアプリケーションに取り組んでいます。これは私のカスタムPagerAdapterです:

private class ImagePagerAdapter extends PagerAdapter {

    private int[] mImages = new int[] { R.drawable.copertinai,
            R.drawable.blui, R.drawable.azzurroi, R.drawable.rossoi,
            R.drawable.gialloi, R.drawable.verdei, R.drawable.rosai,
            R.drawable.grigioi, R.drawable.neroi, R.drawable.arancionei,
            R.drawable.marronei, R.drawable.violai, R.drawable.ulm };

    @Override
    public int getCount() {
        return mImages.length;
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Context context = MainActivity.this;
        RelativeLayout relLayImageView = new RelativeLayout(context);
        relLayImageView.setBackgroundResource(mImages[position]);

        ((ViewPager) container).addView(relLayImageView, new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        return relLayImageView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager) container).removeView((RelativeLayout) object);
        object=null; 
        System.gc();
    }
}

一部のデバイスでは、このコード行が呼び出されると、メモリ不足の例外がランダムに発生します。

relLayImageView.setBackgroundResource(mImages[position]);

しかし、すべてのデバイスで、ページをめくるとlogcatに次のようなものが表示されます。

12-31 00:25:31.655: I/dalvikvm-heap(9767): Grow heap (frag case) to 50.875MB for 10384016-byte allocation

別のアクティビティでユーザーアクションに基づいてメインレイアウトに異なるバックグラウンドリソースを設定すると、同じ問題でアプリが一部のデバイスでクラッシュします。ここにコードがあります:

            btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {


                colorButtons.get(indiceColoreAttuale).setBackgroundResource(
                                unSelectedColorsRes[indiceColoreAttuale]);

                switch (index) {
                case 0:
                    mainLayout.setBackgroundResource(R.drawable.blus);
                    break;
                case 1:
                    mainLayout
                            .setBackgroundResource(R.drawable.azzurros); 
                    break;
                case 2:
                    mainLayout
                            .setBackgroundResource(R.drawable.rossos);
                    break;
                case 3:
                    mainLayout
                            .setBackgroundResource(R.drawable.giallos);
                    break;
                case 4:
                    mainLayout
                            .setBackgroundResource(R.drawable.verdes);
                    break;
                case 5:
                    mainLayout
                            .setBackgroundResource(R.drawable.rosas);
                    break;
                case 6:                     
                    mainLayout
                            .setBackgroundResource(R.drawable.grigios);
                    break;
                case 7:
                    mainLayout
                            .setBackgroundResource(R.drawable.neros);
                    break;
                case 8:
                    mainLayout
                            .setBackgroundResource(R.drawable.arancios);
                    break;
                case 9:
                    mainLayout
                            .setBackgroundResource(R.drawable.marrones);
                    break;
                case 10:
                    mainLayout
                            .setBackgroundResource(R.drawable.violas);
                    break;
                }

                mainLayout.startAnimation(animationShowTextColor);
                mainLayout.setGravity(Gravity.CENTER_HORIZONTAL);
                indiceColoreAttuale = index;
                colorButtons.get(index).setBackgroundResource(
                        selectedColorsRes[index]);

            }
        });

mainLayoutでsetBackgroundResource()を呼び出すと、excepitonが再度実行されます。

よろしくお願いします。

4

2 に答える 2

65

解決しました!ヒントはすべて良かったのですが、本当の問題は「/drawable」フォルダーでした。「/drawable/mdpi」のようなシステムによって考慮される「/drawable」汎用フォルダーにすべての画像があったため、hdpi以上のデバイスで実行していると、画像のサイズが変更され、大きくなりすぎてOutOfMemoryExceptionが発生しました。

現在、「/drawable-nodpi」を使用して画像を保存しています。このフォルダは「/drawable」のように機能しますが、画像のサイズが変更されることはありません。

于 2013-01-05T20:24:17.860 に答える
11

各Androidアプリケーションには、Dalvik VMで使用できるメモリ(ヒープ)が制限されています。一部のデバイスでは32MBで、64MBです。バックグラウンドリソースを設定すると、そのリソースがヒープにロードされます。そのリソースはビットマップとしてロードされます-そのサイズは幅*高さ*ピクセルサイズです。通常、ビットマップは1ピクセルあたり4バイトのARGB画像として読み込まれます。これは、1024x768イメージのロードに1024 * 768 * 4 = 3145728 B = 3072 kB =3MBのヒープが必要であることを意味します。大きな画像を大量にロードすると、すべての空きヒープメモリが消費され、メモリ不足の例外が発生します。

これを修正するには、画像をできるだけ小さくロードすることをお勧めします。画像のサムネイルを表示する場合は、ディスプレイの具体的な部分の解像度よりもそれほど大きくない解像度でロードするだけで十分です。これは、800x600のディスプレイに画像を表示する場合、1024x768の画像をロードするだけでは不十分であることを意味します。BitmapFactoryを使用して、より小さな解像度で画像をロードできます。

メソッドdecodeResource(activity.getResources()、R.drawable.imageId、opts)を使用します。BitmapFactory.Options optsには、画像のサブサンプリングを設定できるパラメータinSampleSizeがあります。また、透明度が必要ない場合は、パラメータinPreferredConfigを使用して、ARGB_8888の代わりにRGB_565を設定できます。

于 2012-12-31T11:41:48.560 に答える