java.lang.OutOfMemoryError при отображении списка изображений в viewFlipper - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь добавить изображения живых плиток в свое приложение. Я проверил функциональность на некоторых устройствах (API> 22), и они работают. Но сейчас я тестирую API 22 и получаю ошибку в названии. Я искал на сайте, и я нашел это особенно полезным OutOfMemoryExceptionGridView . Но я загружаю свои изображения (прямо из папки res) в массив, затем использую видоискатель, чтобы сделать слайд-шоу

Как мне изменить мой блок кода (чтобы исправить основной OOME), так как яВышеуказанные ссылки используют растровые изображения, и я напрямую вызываю res ID.

Это мой код:

@Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container,
                             Bundle savedInstanceState) {

       int[] images = {R.drawable.img1, R.drawable.img2, R.drawable.img3}; //store images into array
        viewFlipper = view.findViewById(R.id.firstTile); //main tile to have slideshow
         for (int image : images) {
            flipperImages(image); //performs the slideshow per image
        }
}
 public void flipperImages(int image) {
        ImageView imageViewFirstTile = new ImageView(getContext());
        imageViewFirstTile.setBackgroundResource(image);
        viewFlipper.addView(imageViewFirstTile);
        viewFlipper.setFlipInterval(12500);
        viewFlipper.setAutoStart(true);
        viewFlipper.setInAnimation(getContext(), android.R.anim.slide_in_left);
        viewFlipper.setOutAnimation(getContext(), android.R.anim.slide_out_right);
    }

Как я могу исправить основную ошибку с помощью этой реализации (вызывая res id изизображения напрямую)?

1 Ответ

0 голосов
/ 17 октября 2019

Если изображения можно уменьшить, чтобы избежать загрузки полноразмерных изображений, я бы посчитал это первым шагом. Нет необходимости загружать полноразмерные растровые изображения в память, если их окно, в котором они отображаются, является частью размера. В вашем текущем подходе изображения не подвергаются выборке, и в результате весь Bitmap загружается в память в полном размере. Таким образом, у вас есть 3 полноразмерных Bitmap с в памяти.

Для подвыборки изображения см. Следующий код. (Источник: https://developer.android.com/topic/performance/graphics/load-bitmap)

/* reqWidth and reqHeight would be the dimensions of your ImageView or some other preferred dimensions. For example, if your Bitmap is 500 X 500 and your ViewFlipper/ImageView is only 100 X 100, passing 100 as reqWidth and 100 as reqHeight will subsample the image until it's dimensions are close to the 100 X 100. This will largely shrink the size loaded into memory. */ 
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}


public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

...