Как лучше хранить картинки приложения в drawable или assets

231
23 декабря 2017, 05:16

Приложение имеет сложный дизайн и по этому было решено делать прорисовку на surfaceView, то есть почти нет никаких xml файлов, все отрисовывается программно. Но есть достаточно большое кол-во небольших png файлов, разного размера. Подскажите каким образом лучше хранить все эти файлы? варианты которые я рассматриваю: drawable - хранить в общей папке и изменять их размер программно, assets - все то же самое и есть третий вариант - загружать все картинки как атлас текстур в одном файле а потом создавать bitmap'ы по областям большого файла. Опишите пожалуйста плюсы и минусы каждого варианта, может есть ещё какие-то варианты с которыми вы сталкивались?(Загрузка через интернет не подходит).

Answer 1

Каталог asset принципиально отличается от drawable тем, что drawable позволяет хранить разные картинки для разных разрешений, ориентаций и локалей. asset же позволяет организовать хранение в виде как бы файлов.

Для вашего случая, я полагаю, drawable таки более предпочителен, поскольку вы можете организовать доступ через идентификаторы картинок, в случае же asset вам придется организовать доступ через как бы файловую систему, с чтением, организацией потока и проч., типа так:

public void loadImageFromAsset() {
    try {
        InputStream ims = getAssets().open("cat.jpg");
        Drawable d = Drawable.createFromStream(ims, null);
        mImage.setImageDrawable(d);
    }
    catch(IOException ex) {
        return;
    }
}

Теперь, вопрос касательно "пилить/не пилить" на картинки для разных dpi, принципиально это отличается только тем что в случае если вы не будете "пилить" картинки, то вы или накалываетесь на OutOfMemoryException на больших картинках, либо программно меняете разрешение картинки через InSampleSize (масштабирование картинки):

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;
}

То есть выводите так:

// сначала проверяете реальный размер битмапа
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
//далее вычисляем inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// теперь декодируем с правильным масштабированием    
options.inJustDecodeBounds = false;
Bitmap bimtap=BitmapFactory.decodeResource(res, resId, options);
//отображаем
imageView.setImageBitmap(bitmap);

Подробнее здесь

Так вот в случае, когда картинки хранятся в раздельных drawable-??dpi - все эти вычисления делаются уже заранее. Тем самым экономится время на масштабирование картинок.

Вам решать, хотите вы заранее масштабировать или вы согласны часть процессорного времени убить на вычисления с масштабированием - зависит от задачи. Если решите не "пилить" картинки на разные dpi - складывайте их в drawable-nodpi.

По-поводу кэширования или асинхронной загрузки картинок. Существует довольно много различных либ, которые решают эту проблему, например universal-image-loader или новомодный Picasso

READ ALSO
Cannot acces java.lang.String

Cannot acces java.lang.String

Почему в записи кода thisname = name; есть ошибка Cannot acces java

223
Как создать свой конвертер в Retrofit?

Как создать свой конвертер в Retrofit?

Как создать свой конвертер в Retrofit?

208
Выгрузка данных в Excel

Выгрузка данных в Excel

Запросом получаю данные в ResultSetКак полученные данные выгрузить в Excel и сразу же открыть полученный Excel файл?

180
Как вынести метод в другой класс?

Как вынести метод в другой класс?

Есть проект с классом MainActivity и соответствующим layout/activity_main

154