Вопрос по android, heap – Android Понимание размеров кучи

29

Я довольно новичок в разработке для Android и, похоже, не понимаю исключения Java Out of Memory. Я знаю, что это означает, что мое приложение превысило бюджет виртуальной машины, но после того, как я гуглял это много раз, я все еще не понимаю эту концепцию. Я боюсь, что мое приложение использует слишком много памяти, потому что у меня есть шесть селекторов кнопок на экран с двумя растровыми изображениями для каждого селектора, которые составляют около 20 КБ каждый в соответствии с вкладкой свойств. На своем рутированном G2x я установил бюджет виртуальной машины в 12 Мб, перезапустил телефон и без проблем запустил свое приложение. Я связываю drawables с каждым onDestroy () и намекаю на GC, чтобы он работал и здесь. После некоторого использования приложения в эмуляторе я нажимаю кнопку «Причина GC». на моем экране DDMS и результаты ID = 1, размер кучи 6,133 МБ, выделено 2,895 МБ, свободно 3,238 МБ, использовано% 47,20, # объектов 52 623.

Здесь я не понимаю, что происходит, мой эмулятор настроен на 24 МБ виртуальной машины. Где этот номер? Реальная проблема, с которой я столкнулся, заключается в том, что, если я установил эмулятор на 16 МБ виртуальной машины, мое приложение зависнет при втором действии с исключением «Недостаточно памяти». Почему это не дает сбой на моем телефоне с установленной виртуальной машиной на 12 МБ или на моем старом телефоне HTC Magic с 12 МБ на складе? Также вы думаете, ребята, мое приложение занимает слишком много памяти? Я понятия не имею, являются ли эти числа 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. Я хотел бы узнать, как программно задавать фон кнопок, но мне нужно иметь функции селектора, такие как фокус, нажатие, несфокусировка, но нажатие и т. Д., Чтобы фон кнопок менялся в зависимости от взаимодействия с пользователем. Я просмотрел документы по этому вопросу, но это кажется ошеломляющим, поэтому я решил, что я начну здесь с основ управления кучами и продолжу свой путь до определения селекторов в коде. Это может не иметь смысла, но есть ли «здоровый» объем памяти, который приложение может выделить, не приближаясь к исключению Out of Memory? Например, если приложение выделило 6 МБ, оно должно быть в порядке, но 8 МБ выдвигало бы его, есть ли ограничения в распределении памяти? Еще раз спасибо, Алекс Локвуд, за твой ответ, который я прочитаю и перечитал еще раз, пока этот материал не станет мне понятен

При работе с OutOfMemoryError необходимо учитывать утечки памяти. Проверять, выписыватьсяWrangling Dalvik: Memory Management in Android jk7

Ваш Ответ

2   ответа
51

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

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

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

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

Error: User Rate Limit Exceededfile sizeError: User Rate Limit ExceededDIMENSIONSError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded John P.
17

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

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

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

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

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

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

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

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

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

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы