Одной из самых распространенных ошибок, которые я обнаружил при разработке Android-приложений, является
java.lang.OutOfMemoryError: Размер растрового изображения превышает бюджет виртуальной машины
.Я часто обнаруживал эту ошибку в «Деятельностях», использующих множество растровых изображений после изменения ориентации: «Действие» уничтожается, создается снова, а макеты «раздуваются» из XML, потребляя память виртуальной машины, доступную для растровых изображений.
Растровые изображения на предыдущемСборщик действий неправильно освобожден сборщиком мусора, потому что он пересек ссылки на свою деятельность.После многих экспериментов я нашел довольно хорошее решение для этой проблемы.
Сначала установите атрибут «id» в родительском представлении макета XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/RootView">
...
Затем на onDestroy()
метод вашей деятельности, вызовите метод unbindDrawables()
, передав ссылку на родительский вид, а затем выполните System.gc()
.
@Override
protected void onDestroy() {
super.onDestroy();
unbindDrawables(findViewById(R.id.RootView));
System.gc();
}
private void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
Этот метод unbindDrawables()
рекурсивно исследует дерево представления и:
- Удаляет обратные вызовы для всех фоновых объектов
- Удаляет дочерние элементы в каждой группе просмотра