Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
#1

OutOfMemoryError в постоянно работающем приложении - Программирование Android

13.12.2016, 19:09. Просмотров 338. Ответов 18
Метки нет (Все метки)

Добрый день.
Есть приложение - стенд с несколькими активити, на которых присутствует множество imagebutton и imageview (картинки скачиваются или обновляются службой). Приложение должно работать постоянно. После некоторого количества переходов с активити на активити происходит OutOfMemoryError. Помогло
Java
1
2
iv.setImageBitmap(null);
bitmap.recycle();
Время жизни программы значительно увеличилось. Но все равно в конечном итоге программа выдает ошибку и перезагружается. System.gc() особо не помогает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2016, 19:09
Здравствуйте! Я подобрал для вас темы с ответами на вопрос OutOfMemoryError в постоянно работающем приложении (Программирование Android):

OutOfMemoryError - Программирование Android
Приложение выдаёт такой лог, и перестаёт показывать изображения. Throwing OutOfMemoryError "Failed to allocate a 1285644 byte allocation...

OutOfMemoryError - Программирование Android
Всем привет. Ошибка заключается в следующем: protected void onCreate(Bundle savedInstanceState) { ...

Сбой OutOfMemoryError - Программирование Android
java.lang.OutOfMemoryError: Failed to allocate a 12960012 byte allocation with 5594672 free bytes and 5MB until OOM at...

Java.lang.OutOfMemoryError - Программирование Android
Помогите, падает приложение с ошибкой нехватки памяти. Делаю добавление фото из галереи телефона, и на 4-5м снимке приложение падает.:( ...

Ошибка java.lang.OutOfMemoryError - Программирование Android
Здравствуйте. В приложении частенько выскакивает ошибки java.lang.OutOfMemoryError BitmapFactory.nativeDecodeAsset() и...

Java.lang.OutOfMemoryError на Samsung Galaxy - Программирование Android
Play Google в разделе Сбой показывает ошибку java.lang.OutOfMemoryError. С ней более-менее все понятно. Но по чему она вылетает...

18
Pablito
2525 / 2004 / 624
Регистрация: 12.05.2014
Сообщений: 7,030
Завершенные тесты: 1
13.12.2016, 19:10 #2
в чем вопрос и где код?
0
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
13.12.2016, 20:05  [ТС] #3
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
btn[i]=new ImageButton(context);
byte[] decodedString = Base64.decode(employees.get(i).employeePhotoData, Base64.DEFAULT);
Img[i]=BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); // здесь, например, вылетает exception
BitmapDrawable bdrawable = new BitmapDrawable(context.getResources(), Img[i]);
btn[i].setImageDrawable(bdrawable);
btn[i].setScaleType(ImageView.ScaleType.FIT_CENTER);
btn[i].setLayoutParams(blp);
btn[i].setBackgroundColor(0);
//..........
@Override
    protected void onPause() {
        super.onPause();
        for (int i = 0;i<Img.length;i++) {
            btn[i].setImageDrawable(null);
            Img[i].recycle();
            Img[i] = null;
        }
        Img = null;
    }
Код exception:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    Process: ru.gkh73.sendsmile, PID: 29984
                                                                    java.lang.OutOfMemoryError
                                                                        at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
                                                                        at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:500)
                                                                        at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:523)
                                                                        at ru.gkh73.sendsmile.EmployeesActivity.createEmpVeiw(EmployeesActivity.java:197)
                                                                        at ru.gkh73.sendsmile.EmployeesActivity.onCreate(EmployeesActivity.java:68)
                                                                        at android.app.Activity.performCreate(Activity.java:5231)
                                                                        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
                                                                        at android.app.ActivityThread.access$800(ActivityThread.java:135)
                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                        at android.os.Looper.loop(Looper.java:136)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5017)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
                                                                        at dalvik.system.NativeStart.main(Native Method)
Вопрос : как избежать переполнения памяти ?
0
demixdn
232 / 179 / 56
Регистрация: 31.10.2016
Сообщений: 406
13.12.2016, 20:17 #4
Самый простой ответ - используйте Glide.
Java
1
2
byte[] bytes = ...
Glide.with(this).load(bytes).asBitmap().into(btn[i]);
0
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
13.12.2016, 21:02  [ТС] #5
Изменил, но память все так же съедается видимо здесь :
Java
1
byte[] decodedString = Base64.decode(employees.get(i).employeePhotoData, Base64.DEFAULT);
Exception вылетает быстрее.
0
vxg
Модератор
3184 / 1987 / 227
Регистрация: 13.01.2012
Сообщений: 7,680
14.12.2016, 10:04 #6
Ul_am, возможно помогут:
1 оптимизация размеров картинок (уменьшение)
2 вызов System.gc() после освобождения всех ссылок
3 добавление <application ... android:largeHeap="true" ... в манифест
4 не особо понятна процедура обновления - кто и как работает с btn - может там ссылки утекают
0
demixdn
232 / 179 / 56
Регистрация: 31.10.2016
Сообщений: 406
14.12.2016, 12:09 #7
Ul_am, тогда предлагаю посмотреть в Memory Monitor и заглянуть в ваш список объектов с помощью Heap Profiling
И дальше оптимизировать использование картинок. Высвобождать ресурсы, использовать WeakReference, уменьшать картинки. Возможно не задавать background для вашей кнопки. Вы привели только часть кода, можно только гадать что и где у вас используется.
0
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
14.12.2016, 12:29  [ТС] #8
vxg,
1-3. Все это уже сделано
4. Есть база данных sqlite (которая обновляется из другой бд службой), в которой хранятся данные и фото. И есть imagebutton и imageview, которые создаются программно и берут данные и фото из этой базы.
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
                if (c.moveToFirst()) {
                    do {
                        List<Employee> employees = new ArrayList<Employee>();
                        Employee e = new Employee();
                        e.departmentID = departmentID;
                        e.employeeName = c.getString(c.getColumnIndex("employeeName"));
                        e.employeeID = c.getString(c.getColumnIndex("employeeID"));
                        e.employeePost = c.getString(c.getColumnIndex("employeePost"));
                        e.employeePhotoName = c.getString(c.getColumnIndex("employeePhotoName"));
                        e.employeePhotoData = c.getString(c.getColumnIndex("employeePhotoData"));
 
                        employees.add(e);
                        e=null;
                    } while (c.moveToNext());
                }
                int empListSize = employees.size();
                ......
 
                for (int i =0 ; i<empListSize; i++) {
                  .....
 
                  btn[i]=new ImageButton(context);
                  byte[] decodedString = Base64.decode(employees.get(i).employeePhotoData, Base64.DEFAULT);
                  Img[i]=BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
                  BitmapDrawable bdrawable = new BitmapDrawable(context.getResources(), Img[i]);
                  btn[i].setImageDrawable(bdrawable);
                  btn[i].setScaleType(ImageView.ScaleType.FIT_CENTER);
                  btn[i].setLayoutParams(blp);
                  btn[i].setBackgroundColor(0);
                  ....
 
}
Помогает обнуление объектов, объем расходуемой памяти растет теперь очень медленно, но все же растет. Не уверен, правильно ли так делать, но временно закрыл вопрос рестартом приложения при отлавливании OutOfMemoryError:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
try
        {
         .......
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        catch (OutOfMemoryError ex)
        {
            Intent intent = new Intent(context, AppRestart.class);
            context.startActivity(intent);
        }
Java
1
2
3
4
5
6
7
public class AppRestart extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.exit(0);
    }
}
0
demixdn
232 / 179 / 56
Регистрация: 31.10.2016
Сообщений: 406
14.12.2016, 12:33 #9
Ul_am, у вас загружается сразу все картинки, насколько я вижу. И сразу же создаются ImageButton? А они все показываются на экране одновременно?
0
Pablito
14.12.2016, 12:42
  #10

Не по теме:

а еще, похоже, что он хранит картинки (наверняка огромного размера) как строки в бд, которые сами по себе отжирают огого памяти пока декодируются в массив байт

0
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
14.12.2016, 12:44  [ТС] #11
demixdn, Большинство помещаются. Проблема не в том, что они много весят или их много (в самих загруженных activity суммарный объем изображений не более 500кб, а обычно гораздо меньше), а в том, что activity генерируют постоянно разные изображения и при,например, сотом или более создании этих activity доступная память переполняется.
0
demixdn
232 / 179 / 56
Регистрация: 31.10.2016
Сообщений: 406
14.12.2016, 12:52 #12
Ul_am, вам не нужны картинки, которые не показываются. Возможно вам стоит использовать RecyclerView для отображения ваших элементов. А этот момент я не понял:
Цитата Сообщение от Ul_am Посмотреть сообщение
сотом или более создании этих activity доступная память
У вас что, куча активити с этими картинками? Возможно вам стоит держать только одно и загружать туда те данные, которые нужны для отображения.

Главный принцип - пока ваши картинки не видны пользователю, они не должны храниться в памяти. Именно bitmap или drawable. Они потребляют просто гигантское кол-во памяти, по сравнению со String или byte[] .
0
vxg
Модератор
3184 / 1987 / 227
Регистрация: 13.01.2012
Сообщений: 7,680
14.12.2016, 12:52 #13
Ul_am, что ЭТО??
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
                    do {
                        List<Employee> employees = new ArrayList<Employee>(); //локальный список который мы создаем каждую итерацию???
                        Employee e = new Employee();
                        e.departmentID = departmentID;
                        e.employeeName = c.getString(c.getColumnIndex("employeeName"));
                        e.employeeID = c.getString(c.getColumnIndex("employeeID"));
                        e.employeePost = c.getString(c.getColumnIndex("employeePost"));
                        e.employeePhotoName = c.getString(c.getColumnIndex("employeePhotoName"));
                        e.employeePhotoData = c.getString(c.getColumnIndex("employeePhotoData"));
 
                        employees.add(e);
                        e=null;
                    } while (c.moveToNext());
0
Ul_am
1 / 1 / 0
Регистрация: 10.11.2014
Сообщений: 79
14.12.2016, 12:54  [ТС] #14
Паблито,
а еще, похоже, что он хранит картинки (наверняка огромного размера) как строки в бд, которые сами по себе отжирают огого памяти пока декодируются в массив байт
Я делаю так
Java
1
2
3
4
byte[] decodedString = Base64.decode(employees.get(i).employeePhotoData, Base64.DEFAULT);
.....
 
decodedString = null;
Добавлено через 2 минуты
vxg, нет, опечатка, извиняюсь
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 List<Employee> employees = new ArrayList<Employee>(); 
.....
if (c.moveToFirst()) {
                    do {
                       
                        Employee e = new Employee();
                        e.departmentID = departmentID;
                        e.employeeName = c.getString(c.getColumnIndex("employeeName"));
                        e.employeeID = c.getString(c.getColumnIndex("employeeID"));
                        e.employeePost = c.getString(c.getColumnIndex("employeePost"));
                        e.employeePhotoName = c.getString(c.getColumnIndex("employeePhotoName"));
                        e.employeePhotoData = c.getString(c.getColumnIndex("employeePhotoData"));
 
                        employees.add(e);
                        e=null;
                    } while (c.moveToNext());
                }
0
vxg
Модератор
3184 / 1987 / 227
Регистрация: 13.01.2012
Сообщений: 7,680
14.12.2016, 12:57 #15
Ul_am, откуда берутся Img и btn?
0
14.12.2016, 12:57
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.12.2016, 12:57
Привет! Вот еще темы с ответами:

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

Как в JPanel -JTextField в работающем приложении поменять значение? - Java
Пишу программу, которая загружает в указанную папку по ссылке файлы. есть интерфейс, на панели которого отображаются список...

.NET 2.x Почему OpenFileDialog и SaveFileDialog не отображаются при работающем приложении на форме - C#
Среда: VS_2008 Создаю пустой проект WindowsFormApplication, в котором не получается разместить диалоги открытия файлов и сохранения. ...

Мышка в приложении постоянно в состоянии загрузки - C++
В общем, пишу небольшую игру, если важно, с применением DirectX, и в начале запуска естественно меню мышка постоянно кружком(Win 7), как...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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