Проблема при переработке растрового изображения, полученного из BitmapDrawable.

Я загружаю растровое изображение для использования в качестве текстуры в моем приложении OpenGLES 2.0.

Если я загружаю и использую растровое изображение через Bitmapfactory, тогда все в порядке. Вот так:

Загрузить

 public void loadBitmaps{

    backgrounds= BitmapFactory.decodeResource(view.getResources(), R.drawable.backgrounds, BMFOptions);
    ...

Использовать

//Apply as texture to OpenGL Quad

Переработка

backgrounds.recycle();

.

Теперь проблема...........

.

Когда я загружаю растровое изображение как bitmapDrawable, у меня возникают проблемы (объяснено ниже кода). Вот так:

.

Объявить BitmapDrawable на уровне класса

public class Res{

    BitmapDrawable bd;
    ...

Загрузить

public void loadBitmaps(){

    bd = (BitmapDrawable) view.getResources().getDrawable(R.drawable.backgrounds);
    backgrounds = bd.getBitmap();
    ...

Использовать

//Apply as texture to OpenGL Quad

Переработка

backgrounds.recycle();

При этом это работает в первый раз, но если я затем нажму назад, чтобы выйти, и перезапущу приложение, текстуры не будут отображаться, и все, что я получаю, это черные квадраты.

Если я сделаю что-либо из следующего, это решит проблему, и я хотел бы знать, почему ......

  • Либо переместите объявление bd из переменной класса, поэтому я использую:

BitmapDrawable bd = (BitmapDrawable) view.getResources().getDrawable(R.drawable.backgrounds);

  • Или просто сделайте это после создания растрового изображения:

бд = ноль;

  • наконец, я также могу просто не перерабатывать растровое изображение, но это не вариант

Примечание Мне нужно получить доступ к растровому изображению таким образом, а не использовать BitmapFactory, поскольку я обращаюсь к нему через псевдоним XML.


person Zippy    schedule 15.09.2014    source источник


Ответы (1)


Экземпляры Drawable кэшируются и совместно используются, поэтому при вызове getDrawable() он загрузит тот, который в настоящее время кэширован, а не создаст новое растровое изображение. Если вы переработаете базовое растровое изображение, это вызовет проблемы с будущим использованием. Скорее всего, вы захотите сделать копию чертежа перед его изменением:

BitmapDrawable bmpDrawable = (BitmapDrawable) view.getResources()
        .getDrawable(R.drawable.backgrounds);
Bitmap original = bmpDrawable.getBitmap();
Bitmap copy = original.copy(original.getConfig(), true);

Дополнительную информацию о переносимых мутациях см. в этой записи в блоге.

person Kevin Coppock    schedule 15.09.2014
comment
Спасибо @kcoppock за эту информацию, я обязательно прочитаю блог, но не могли бы вы сказать мне, держит копию, плохо (с точки зрения памяти) и (опять же с точки зрения памяти), что-то не так с методом, который я нашел, например просто обнулить bd в моем примере выше? Мои растровые изображения довольно большие, и поскольку я применяю их как текстуры (это атласы текстур), поэтому я хочу избавиться от основного растрового изображения, как только это будет сделано. Поэтому я не хочу держать их где-либо еще. Я просто пытаюсь быть настолько сознательным, насколько могу - спасибо - person Zippy; 16.09.2014
comment
Кроме того, я не понимаю, что на самом деле я выхожу из своего приложения и перезапускаю его, поэтому все должно быть не так, как при первом запуске приложения? - person Zippy; 16.09.2014
comment
Простое закрытие приложения не удаляет процесс из памяти, поэтому нет гарантии, что они будут загружены повторно. Есть ли способ избежать использования псевдонимов XML для них и просто загрузить растровые изображения напрямую? Я совершенно уверен, что нет способа получить их, не проходя через Drawables, и в этом случае вы не можете контролировать, когда ресурсы перерабатываются. - person Kevin Coppock; 16.09.2014
comment
Кроме того, я обновил свой ответ, так как понял, что mutate() на самом деле не меняет базовое растровое изображение - только состояние рисуемого. - person Kevin Coppock; 16.09.2014
comment
Я долго искал способы добраться до псевдонимов, но, к сожалению, похоже, что использование рисунков - мой единственный вариант. Будет ли обнуление объекта и переработка растрового изображения, как я сейчас делаю, эффективным обходным путем (чтобы заставить его каждый раз создавать новый) - я думаю, что это было бы лучше всего для освобождения памяти - вы согласны? Я действительно не хочу, чтобы экземпляры этого большого растрового изображения оставались без дела после того, как оно было применено к моим объектам OpenGL или приложение закрылось. У меня есть много других растровых изображений, которые я загружаю с помощью Bitmapfactory, и я их все перерабатываю. Спасибо за вашу помощь. - person Zippy; 16.09.2014
comment
Если вы загружаете ресурсы, вы не можете повторно использовать базовое растровое изображение, иначе вы вызовете всевозможные сумасшествия. Обнуление объекта не приведет к тому, что Android освободит кеш (он должен обрабатывать это автоматически, когда требуется больше памяти). - person Kevin Coppock; 16.09.2014
comment
Спасибо @Kcoppock, я действительно хочу кое-что понять. Если я загружу растровое изображение как рисуемое, привяжу его как текстуру GL, а затем переработаю растровое изображение (поскольку оно больше не требуется, насколько я понимаю, текстура GL в основном является копией растрового изображения) - почему переработка вызвать проблемы, так как это больше не понадобится во время этого сеанса, то есть до тех пор, пока приложение не будет закрыто и перезапущено. Я просто спрашиваю, потому что я немного запутался в этой части!!!! В противном случае ваш метод кажется разумным. - person Zippy; 16.09.2014
comment
Процесс вашего приложения может оставаться в памяти дольше (иногда гораздо дольше), чем ваши действия. Даже после того, как все ваши действия завершены, ваше приложение может оставаться в памяти и удерживать кешированные ресурсы, а также может некоторое время оставаться активным для более быстрого запуска или запуска службы, или получения широковещательных сообщений и т. д.). По сути, вы перерабатываете то, что Android все еще использует (даже если это не так). - person Kevin Coppock; 16.09.2014
comment
Ах я вижу. В этом есть смысл. В общем, я могу сделать переработку, но это будет означать, что я заставляю свои ресурсы перезагружаться, тогда как если бы я не перерабатывал их, они могли по-прежнему быть доступны после выхода пользователя. приложение, если они решили перезапустить. Я никогда не думал об этом таким образом, хотя я до сих пор не понимаю, почему у меня возникнут проблемы с повторной загрузкой и повторной загрузкой каждый раз, но спасибо, я понимаю ваши мысли относительно вашего ответа. Ответ принят. - person Zippy; 16.09.2014
comment
Кстати, @Kcoppock, ваш оригинальный ответ (используйте .mutate()) тоже работает! - person Zippy; 16.09.2014
comment
Странный. Это не должно, ха-ха. Я бы не обязательно полагался на то, что это сработает; они, возможно, изменили то, как это работает внутри, с тех пор, как появилось это сообщение в блоге. Хотя интересно узнать! - person Kevin Coppock; 16.09.2014