Подтвердить что ты не робот

Android Понимание размеров кучи

Я новичок в разработке Android, и, похоже, я не могу понять исключение Java Out of Memory. Я знаю, это означает, что мое приложение перешло на бюджет VM, но после Googling это много раз, я все еще не понимаю эту концепцию. Я боюсь, что мое приложение использует слишком много памяти, потому что у меня есть шесть переключателей на один экран с двумя растровыми изображениями для каждого селектора, каждый из которых составляет по 20 кб в соответствии со вкладкой свойств. На моем корневом G2x я установил бюджет VM на 12mb, перезапустил свой телефон и без проблем запускал мое приложение. Я не привязываю чертежи к каждому onDestroy() и намекает на GC, чтобы работать здесь также. После использования приложения в эмуляторе я нажимаю "Причина GC" на моем экране DDMS, и результаты ID = 1, размер кучи 6.133 MB, выделено 2.895MB, бесплатно 3.238 MB,% использовано 47.20, # Объекты 52,623.

Вот где я не понимаю, что происходит, мой эмулятор настроен на 24 МБ виртуальной машины. Где этот номер? Фактическая проблема, с которой я столкнулась, заключается в том, что если я установил эмулятор на 16 МБ виртуальной машины, мое приложение выйдет из строя во втором действии с исключением Out of Memory. Почему это не сбой на моем телефоне с установленной VM до 12 МБ или на моем старом телефоне HTC Magic с 12 МБ акций VM? Также вы, ребята, думаете, что мое приложение занимает слишком много памяти? Я не знаю, хороши ли эти номера DDMS или нет. Спасибо за ваше время.

Что касается моего кода, то у меня есть все изображения, указанные в XML-макетах. Я ничего не делаю с ними программно, кроме как добавлять к ним слушателей. Я нашел здесь этот фрагмент кода, и я добавил его ко всем действиям, которые у меня есть...

@Override
protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.myRootLayout));
    System.gc();
}

private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

В противном случае все, что я делаю, добавляет onClickListeners к кнопкам с фонов PNG. Я хотел бы узнать, как программировать фоновые кнопки кнопок, но мне нужно иметь функции селектора, такие как фокусировка, прессование, нефокусировка, но нажатие и т.д., Чтобы изменить фоны кнопок в зависимости от взаимодействия пользователя. Я просмотрел документы об этом, но кажется, что это потрясающе, поэтому я решил, что начинаю здесь с основ управления Heaps и прокладываю себе путь до указания селекторов в коде. Возможно, это не имеет смысла, но есть ли "здоровый" объем распределения памяти, который приложение может выделять, не приблизившись к исключению Out of Memory? Например, если приложение выделяет 6 МБ, оно должно быть прекрасным, но 8 МБ будет его подталкивать, существуют ли ограничения в распределении памяти? Еще раз спасибо Алексу Локвуду за ваш ответ. Я собираюсь прочитать и перечитать его снова, пока этот материал не будет иметь для меня смысл.

4b9b3361

Ответ 1

Когда вы устанавливаете бюджет VM на своем эмуляторе/устройстве, то, что вы делаете, сообщает куче максимальный размер, который ему разрешен. Во время выполнения куча динамически растет по размеру, так как Dalvik VM запрашивает системную память из операционной системы. VM Dalvik обычно начинается с выделения относительно небольшой кучи. Затем после каждого запуска GC он проверяет, сколько свободной памяти кучи есть. Если отношение свободной кучи к общей куче слишком мал, тогда Dalvik VM добавит больше памяти в кучу (до максимального размера сконфигурированной кучи).

При этом причина, по которой вы не видите "24 МБ" на экране DDMS, заключается в том, что куча не достигла максимального размера. Это позволяет Android хорошо использовать уже небольшой объем памяти, доступный на карманных устройствах.

Что касается того, почему ваше приложение рушится на эмуляторе, а не на вашем телефоне, это кажется странным (вы уверены, что цифры верны?). Однако вы должны иметь в виду, что память управляется динамически и общее использование памяти определяется на основе ряда внешних факторов (скорость/частота, с которой выполняется сбор мусора и т.д.).

Наконец, по причинам, о которых я говорил выше, было бы трудно сказать, насколько хорошо ваше приложение управляет памятью на основе одной строки информации, указанной выше. Нам действительно нужно увидеть некоторые из вашего кода. OutOfMemoryError, безусловно, стоит беспокоиться, однако, я бы определенно посмотрел на использование вашей памяти приложения. Одна вещь, которую вы можете рассмотреть, - это образец изображений растровых изображений во время выполнения с вызовами inSampleSize с использованием класса BitmapFactory. Это может помочь уменьшить объем памяти, необходимый для загрузки выносных растровых изображений. Либо это, либо вы могли бы уменьшить разрешение ваших чертежей (хотя для каждого из них было отлично 20 kb).

Ответ 2

Даже если ваше приложение не достигает ограничения на 24 байта (зависит от устройства), вы все равно можете столкнуться с сбоями, потому что Android занимает некоторое время, чтобы увеличить пространство кучи для вашего приложения.

В моей ситуации я создавал и сбрасывал несколько изображений за небольшой промежуток времени.

Довольно часто я получал OutOfMemoryError.

Кажется, Android не был достаточно быстрым, чтобы вырастить кучу пространства для моего приложения.

Я считаю, что я решил эту проблему, используя параметр largeHeap в файле манифеста. С этой настройкой Android оставляет больше свободной памяти каждый раз, когда она вырастает в куче, сводя к минимуму вероятность поражения текущего предела.

Я не использую ограничение 24mb, но этот largeHeap conf был весьма удобен.

Вам просто нужно установить largeHeap="true" в теге приложения вашего AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:theme="@style/AppTheme" >

Тем не менее, следите за тем, чтобы вы обращали внимание на изображения, например, @Alex Lockwood.