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