Android setBackgroundResource导致内存不足

The*_*ind 20 memory android exception android-viewpager android-drawable

我正在开发一个游戏手册应用程序,在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

在某些设备中,当调用此代码行时,它会随机导致内存不足异常

relLayImageView.setBackgroundResource(mImages[position]);
Run Code Online (Sandbox Code Playgroud)

但是在所有设备中,当我翻页时,我在logcat中看到类似的东西:

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

在另一个Activity中,应用程序也会在某些设备中因同一问题而崩溃我根据用户操作将不同的后台资源设置为主布局.这里的代码:

            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]);

            }
        });
Run Code Online (Sandbox Code Playgroud)

当我在mainLayout上调用setBackgroundResource()时,它再次运行.

我希望你能提前帮助我解决这个问题!

The*_*ind 64

我解决了!所有的提示都很好,但真正的问题是"/ drawable"文件夹!我把系统所考虑的"/ drawable"通用文件夹中的所有图片都用作"/ drawable/mdpi",所以当我在hdpi或更高版本的设备上运行时,图像被调整大小,变得太大而导致OutOfMemoryException!

现在我正在使用"/ drawable-nodpi"来存储我的图像.此文件夹的工作方式类似于"/ drawable",但图像永远不会调整大小!


tom*_*zek 10

每个Android应用程序都有有限的内存(堆),可供Dalvik VM使用.在某些设备上它是32 MB,它是64 MB.设置后台资源时,在堆上加载该资源.该资源作为Bitmap加载 - 它的大小是宽*高*像素大小.Usualy位图作为ARGB图像加载,每个像素有4个字节.这意味着加载1024x768图像需要1024*768*4 = 3145728 B = 3072 kB = 3 MB堆.当您加载大量大图像时,它会消耗所有可用堆内存并导致内存不足异常.

要解决此问题,最好尽可能小地加载图像 - 当您显示图像的缩略图时,只需将其加载到分辨率不足以大于显示器的具体部分的分辨率.这意味着当您在800x600显示器上显示图像时,仅加载1024x768图像是不够的.您可以使用BitmapFactory以较小的分辨率加载图像.

使用方法decodeResource(activity.getResources(),R.drawable.imageId,opts).BitmapFactory.Options opts具有参数inSampleSize,您可以在其中设置图像的子采样.如果您不需要透明度,也可以使用参数inPreferredConfig来设置RGB_565而不是ARGB_8888.