#android #memory-leaks #imageview #profiler
#Android #утечки памяти #просмотр изображений #профилировщик
Вопрос:
У меня есть действие, которое, похоже, приводит к утечке памяти, как показано ниже. Однако утечка canary, похоже, не дает никаких утечек или уведомлений. Если я принудительно собираю мусор, это почти ничего не дает.
В этом упражнении я динамически создаю imageviews и layouts, а затем помещаю их в scrollview. Пример этого приведен ниже:
dynamicUI = new DynamicUI(getApplicationContext());
TextView textViewTitle = dynamicUI.headerTextView(exercises[i].name);
// Horizontal layout with tools icon and exercise time text
LinearLayout layoutTime = new LinearLayout(new ContextThemeWrapper(this, R.style.exercise_info_layout), null, 0);
layoutTime.addView(dynamicUI.iconImage(R.drawable.tools_icon));
layoutTime.addView(dynamicUI.captionTextView(exercises[i].time));
layoutTime.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
DynamicUI — это класс, который я написал для создания представлений одинаковым образом во всем моем приложении. Вот пример метода:
public ImageView iconImage(int id){
ImageView imageView = new ImageView(new ContextThemeWrapper(context, R.style.ButtonImageSmall));
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams((int) (50 * scale), (int) (50 * scale));
lp.setMargins((int) (10*scale), (int) (10*scale), (int) (10*scale), (int) (10*scale));
imageView.setLayoutParams(lp);
imageView.setImageDrawable(context.getResources().getDrawable(id));
return imageView;
}
Есть несколько представлений, которые я добавляю к дочернему элементу scrollview:
LinearLayout layoutVertical = dynamicUI.exerciseContainer();
layoutVertical.addView(textViewTitle);
layoutVertical.addView(imageViewCover);
layoutVertical.addView(layoutTime);
layoutVertical.addView(layoutDiff);
scrollLayoutChild.addView(layoutVertical);
Существует довольно много таких макетов, 1-5 или около того. Они генерируются из базы данных SQLite:
DatabaseHelper db = new DatabaseHelper(getApplicationContext());
Я попытался присвоить значение null как моим объектам db, так и dynamicUI в конце onCreate (), и, похоже, это ничего не дает:
// stop memory leak?
dynamicUI = null;
db = null;
Ответ №1:
Вы никогда не должны использовать контекст приложения для создания представлений. Вы должны использовать контекст Activity действия, которое отображает представление. Это потому, что просмотры ограничены действием, я не знаю, что это ваша утечка памяти, но это определенно ошибка, которая может привести к странному поведению. Как минимум, его темы и ресурсы могут быть некорректными.
Комментарии:
1. Итак, если я использую getApplicationContext, означает ли это, что ImageViews существуют для всего приложения и не могут быть собраны в мусор? И если я использую Activity.this вместо этого, они будут удалены по мере выполнения activities?
2. Я не могу с уверенностью сказать, есть ли другая связь, из-за которой они также остаются резидентными, или нет. Лучший способ проверить это — взять дамп кучи и посмотреть на ссылки. Но поскольку представления принадлежат одному действию, они должны использовать контекст действия для их создания, иначе из-за неправильной инициализации могут возникнуть всевозможные ошибки.