Android setBackgroundResource вызывают нехватку памяти excepiton - программирование
Подтвердить что ты не робот

Android setBackgroundResource вызывают нехватку памяти excepiton

Я работаю над приложением для игр, которое отображает 12 просмотров в ViewPager. Это мой пользовательский 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]);

            }
        });

Он запускает excepiton снова, когда я вызываю setBackgroundResource() на mainLayout.

Надеюсь, вы поможете мне решить эту проблему, спасибо заранее!

4b9b3361

Ответ 1

Я решил! Все ваши подсказки были хорошими, но реальной проблемой была папка "/drawable" ! У меня были все фотографии в общей папке "/drawable" , которая рассматривается системой как "/drawable/mdpi", поэтому, когда я работал на устройствах с hdpi или больше, изображения менялись и становились слишком большими, что вызывало OutOfMemoryException!

Теперь я использую "/drawable-nodpi" для хранения моих изображений. Эта папка работает как "/drawable" , но изображения никогда не изменяются!

Ответ 2

Каждое приложение Android имеет ограниченную память (кучу), которую может использовать Dalvik VM. Это 32 МБ на некоторых устройствах - 64 МБ. Когда вы устанавливаете фоновый ресурс, вы загружаете этот ресурс в кучу. Этот ресурс загружается как Bitmap - размер - ширина * высота * размер пикселя. Обычные растровые изображения загружаются как изображения ARGB с 4 байтами на пиксель. Это означает, что загрузка изображения 1024x768 занимает 1024 * 768 * 4 = 3145728 B = 3072 kB = 3 МБ в куче. Когда вы загружаете большое количество больших изображений, он потребляет всю свободную память кучи и вызывает исключение из памяти.

Чтобы исправить это, лучше загружать изображения как можно меньше - когда вы показываете миниатюру изображения, достаточно загрузить его в разрешении, которое не намного больше, чем разрешение конкретной части дисплея. Это означает, что при отображении изображения на экране 800x600 недостаточно загрузить изображение 1024x768. Вы можете использовать BitmapFactory для загрузки изображения с меньшим разрешением.

Использовать метод decodeResource (activity.getResources(), R.drawable.imageId, opts). BitmapFactory.Options opts имеет параметр inSampleSize, где вы можете установить подвыборки изображения. Также параметр inPreferredConfig может использоваться для установки RGB_565 вместо ARGB_8888 в случае, если вам не нужна прозрачность.