Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 5.00
Stylish2013
7 / 7 / 1
Регистрация: 20.04.2013
Сообщений: 666
#1

Изменить код работы с Bitmap в связи с OutOfMemoryError - Android

09.08.2013, 16:47. Просмотров 1686. Ответов 12
Метки нет (Все метки)

Прочитал статью ( http://habrahabr.ru/post/161027/#habracut ) и хотел бы изменить свой код, так как в данный момент приложение испытывает OutOfMemoryError.

У меня есть код:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Override
        protected HashMap<String, Object> doInBackground(
                HashMap<String, Object>... hm) {
 
            InputStream iStream = null;
            String imgUrl = (String) hm[0].get("imageLogo_path");
            int position = (Integer) hm[0].get("position");
 
            URL url;
            try {
                url = new URL(imgUrl);
                HttpURLConnection urlConnection = (HttpURLConnection) url
                        .openConnection();
                urlConnection.connect();
                iStream = urlConnection.getInputStream();
                File cacheDirectory = getBaseContext().getCacheDir();
                File tmpFile = new File(cacheDirectory.getPath() + "/wpta_"
                        + position + ".png");
                FileOutputStream fOutStream = new FileOutputStream(tmpFile);
                Bitmap b = BitmapFactory.decodeStream(iStream);
                b.compress(Bitmap.CompressFormat.PNG, 100, fOutStream);
                fOutStream.flush();
                fOutStream.close();
 
                HashMap<String, Object> hmBitmap = new HashMap<String, Object>();
                hmBitmap.put("imageLogo", tmpFile.getPath());
                hmBitmap.put("position", position);
                return hmBitmap;
 
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
а в статье имеется пример:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
InputStream in = ... //Ваш InputStream
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int origWidth = o.outWidth; //исходная ширина 
int origHeight = o.outHeight; //исходная высота 
int bytesPerPixel = 2 //соответствует RGB_555 конфигурации
int maxSize = 480 * 800 * bytesPerPixel; //Максимально разрешенный размер Bitmap
int desiredWidth = …; //Нужная ширина
int desiredHeight = …; //Нужная высота
int desiredSize = _ desiredWidth * _ desiredHeight * bytesPerPixel; //Максимально разрешенный размер Bitmap для заданных width х height
if (desiredSize < maxSize) maxSize = desiredSize;
int scale = 1; //кратность уменьшения
int origSize = origWidth * origHeight * bytesPerPixel;
//высчитываем кратность уменьшения
if (origWidth > origHeight) {
    scale = Math.round((float) origHeight / (float) desiredHeight);
} else {
    scale = Math.round((float) origWidth / (float) desiredWidth);
}
 
o = new BitmapFactory.Options();
o.inSampleSize = scale;
o.inPreferredConfig = Config.RGB_565;
            
in = … //Ваш InputStream. Важно - открыть его нужно еще раз, т.к второй раз читать из одного и того же InputStream не разрешается (Проверено на ByteArrayInputStream и FileInputStream).
Bitmap bitmap = BitmapFactory.decodeStream(in, null, o); //Полученный Bitmap
но как я не пытался, совместить код у меня не получается. Листвью с записями отображается но без картинок. Сыпятся разные ошибки.
- resolveUri failed on bad bitmap uri: /data/data/com.androidcompany.projectmy/cache/wpta_0.png
- SkImageDecoder::Factory returned null
а иногда и вовсе не запускается крошится.

проверял папку кеша, а она пустая.

Помогите всё сделал правильно, чтобы работало. Может я что-то упускаю...
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
09.08.2013, 18:55     Изменить код работы с Bitmap в связи с OutOfMemoryError #2
После работы с Bitmap вызывайте bmp.recycle(); Это раз. Второе: к чему такие сложности? Замените BitmapFactory обычной записью в файл на прямую и все проблемы отпадут:
Java
1
2
3
4
5
6
7
8
 int read = 0;
 byte[] bytes = new byte[1024];
 
 while ((read = iStream.read(bytes)) != -1) {
 fOutStream.write(bytes, 0, read);
 }
 iStream.close();
 fOutStream.close();
Третье, CacheDir нужно использовать с большой осторожностью, ибо место ограничено (несколько мб), а сама она не очищается. Не по православному это. Используйте ExternalStorageDirectory.
И последнее, вы всё это выводите в ListView? Почему не использовать небезызвестные LazyList или UniversalImageLoader?
Stylish2013
7 / 7 / 1
Регистрация: 20.04.2013
Сообщений: 666
09.08.2013, 19:43  [ТС]     Изменить код работы с Bitmap в связи с OutOfMemoryError #3
да всё вывожу в ListView. Использую всё так потому, что изначально было так сделано, а чтоб переделать - это будет не просто.

Добавлено через 5 минут
Цитата Сообщение от Wenceslaus Посмотреть сообщение
После работы с Bitmap вызывайте bmp.recycle(); Это раз. Второе: к чему такие сложности?
в связи с OutOfMemoryError. Хочу ужимать качество. Чтобы меньше весели фотки.

Цитата Сообщение от Wenceslaus Посмотреть сообщение
Замените BitmapFactory обычной записью в файл на прямую и все проблемы отпадут:
заменил, да работает. Но а чем оно отличается от того что у меня было???
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
09.08.2013, 20:16     Изменить код работы с Bitmap в связи с OutOfMemoryError #4
Цитата Сообщение от Stylish2013 Посмотреть сообщение
Но а чем оно отличается от того что у меня было???
Тем, что используя BitmapFactory вы грузите всё изображение в память (+ забываете его выгрузить), а записывая на прямую, вы держите в памяти только 1024 (new byte[1024]) байта, 1 Кб. Посему никаких OutOfMemoryError быть не может.
Stylish2013
7 / 7 / 1
Регистрация: 20.04.2013
Сообщений: 666
09.08.2013, 20:32  [ТС]     Изменить код работы с Bitmap в связи с OutOfMemoryError #5
Тем, что используя BitmapFactory вы грузите всё изображение в память (+ забываете его выгрузить), а записывая на прямую, вы держите в памяти только 1024 (new byte[1024]) байта, 1 Кб. Посему никаких OutOfMemoryError быть не может.

да сейчас таких проблем нет. Но у меня притормаживает при скролинге из за записи в файл это может быть?
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
09.08.2013, 21:27     Изменить код работы с Bitmap в связи с OutOfMemoryError #6
http://developer.android.com/trainin...ad-bitmap.html
verylazy
Заблокирован
09.08.2013, 21:38     Изменить код работы с Bitmap в связи с OutOfMemoryError #7
по этой ссылке пишут как делать маленькие превьюшки, а как быть с разными дисплеями?
100 на 100 пикселей на телефоне и на топовом планшете будут разного размера
получается что либо все в абсолютных координатах и размерах, либо везде пересчитывать по какой-то формуле?
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
09.08.2013, 22:48     Изменить код работы с Bitmap в связи с OutOfMemoryError #8
verylazy, используйте weight

Добавлено через 35 секунд
+ http://developer.android.com/trainin...s/screens.html
verylazy
Заблокирован
09.08.2013, 23:11     Изменить код работы с Bitmap в связи с OutOfMemoryError #9
хорошая ссылка, я до нее еще не дочитал

Вот к примеру есть 10 фотографий в jpg, которые лежат на карте памяти. Как их отобразить на экране? Я пока дошел только до вот такого способа
Java
1
img.setImageBitmap(BitmapFactory.decodeFile("путь и имя файла"));
при этом все равно вычитывается весь файл и битмап занимает место в памяти равное Ш*В*4 картинка 640*480 занимает 1.2 метра примерно.
И как тут мне поможет weight? Не могу пока уложить это в голове.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
09.08.2013, 23:59     Изменить код работы с Bitmap в связи с OutOfMemoryError #10
Цитата Сообщение от verylazy Посмотреть сообщение
при этом все равно вычитывается весь файл и битмап занимает место в памяти равное Ш*В*4 картинка 640*480 занимает 1.2 метра примерно.
И как тут мне поможет weight? Не могу пока уложить это в голове.
для этого самая первая моя ссылка.
verylazy
Заблокирован
10.08.2013, 08:57     Изменить код работы с Bitmap в связи с OutOfMemoryError #11
ааа, все понял!
утро - вечера мудреннее, спасибо
Stylish2013
7 / 7 / 1
Регистрация: 20.04.2013
Сообщений: 666
10.08.2013, 12:20  [ТС]     Изменить код работы с Bitmap в связи с OutOfMemoryError #12
Цитата Сообщение от Stylish2013 Посмотреть сообщение
Но у меня притормаживает при скролинге из за записи в файл это может быть?
ответьте пожалуйста прямо если можно на вопрос? из ссылки:
Цитата Сообщение от V0v1k Посмотреть сообщение
http://developer.android.com/trainin...ad-bitmap.html
ответа не выявил.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.08.2013, 11:30     Изменить код работы с Bitmap в связи с OutOfMemoryError
Еще ссылки по теме:

Сбой OutOfMemoryError Android
OutOfMemoryError Android
Android Java.lang.OutOfMemoryError
Переписать код для работы с html, C# => Java Android
Android OutOfMemoryError в постоянно работающем приложении

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Wenceslaus
Android Developer
129 / 129 / 4
Регистрация: 05.07.2013
Сообщений: 205
12.08.2013, 11:30     Изменить код работы с Bitmap в связи с OutOfMemoryError #13
Stylish2013, отвечу я, если никто не против. При скроллинге притормаживает не из-за записи в файл (хотя это косвенно связано), а из-за того, что загружаемые изображения слишком велики и затрачивается длительное время и много ресурсов на их обработку и отображение. Чтобы этого не происходило вам V0v1k посоветовал прочесть эту ссылку, где и описано, как уменьшить затраты на отображение изображения (конкретно решение: уменьшить размер загружаемого в ListVeiw изображения). Код и подробное описание по ссылке выше.
Yandex
Объявления
12.08.2013, 11:30     Изменить код работы с Bitmap в связи с OutOfMemoryError
Ответ Создать тему
Опции темы

Текущее время: 23:13. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru