Android - просмотр. Поверхность OutOfResourcesException - PullRequest
4 голосов
/ 01 июля 2011

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

Журнал ошибок:

07-01 09:54:42.913: INFO/ActivityManager(1279): Starting: Intent { cmp=com.site.android.conferencecompanion/.Search } from pid 31290
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): /dev/pmem: no more pmem available
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): couldn't open pmem (No such file or directory)
07-01 09:54:43.013: ERROR/msm7x30.gralloc(1279): gralloc failed err=Out of memory
07-01 09:54:43.013: WARN/GraphicBufferAllocator(1279): alloc(480, 800, 1, 00000133, ...) failed -12 (Out of memory)
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279): Allocated buffers:
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x290740: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x307448:   60.00 KiB |  102 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x32e4c0:   71.25 KiB |  480 ( 480) x   38 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x3caad8:   60.00 KiB |  102 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x4a47f8: 1346.25 KiB |  480 ( 480) x  718 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x4f9710: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x54c500: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x5d1c00: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x5f5f98: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x604600:   60.00 KiB |  126 ( 128) x  120 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x60a3d0:  750.00 KiB |  480 ( 480) x  800 |        4 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x661270: 1428.75 KiB |  480 ( 480) x  762 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x6830b8:  750.00 KiB |  480 ( 480) x  800 |        4 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x70e0e8: 1500.00 KiB |  480 ( 480) x  800 |        1 | 0x00000133
07-01 09:54:43.013: DEBUG/GraphicBufferAllocator(1279):   0x71f238:   71.25 KiB |  480 ( 480) 
07-01 09:54:43.013: ERROR/SurfaceFlinger(1279): Layer::requestBuffer(this=0x189d50), index=0, w=480, h=800 failed (Out of memory)
07-01 09:54:43.013: ERROR/Surface(31290): Surface (identity=4545) requestBuffer(0, 0, 0, 0, 00000033) returned a buffer with a null handle
07-01 09:54:43.013: ERROR/Surface(31290): getBufferLocked(0, 0, 0, 0, 00000033) failed (Out of memory)
07-01 09:54:43.013: ERROR/Surface(31290): dequeueBuffer failed (Out of memory)
07-01 09:54:43.013: ERROR/ViewRoot(31290): OutOfResourcesException locking surface
07-01 09:54:43.013: ERROR/ViewRoot(31290): android.view.Surface$OutOfResourcesException
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.Surface.lockCanvasNative(Native Method)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.Surface.lockCanvas(Surface.java:314)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.draw(ViewRoot.java:1457)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1259)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1860)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.os.Looper.loop(Looper.java:123)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at android.app.ActivityThread.main(ActivityThread.java:3839)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at java.lang.reflect.Method.invokeNative(Native Method)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at java.lang.reflect.Method.invoke(Method.java:507)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
07-01 09:54:43.013: ERROR/ViewRoot(31290):     at dalvik.system.NativeStart.main(Native Method)
07-01 09:54:43.203: INFO/ActivityManager(1279): Displayed com.site.android.conferencecompanion/.Search: +292ms

adb shell dumpsys window раскрывает следующее:

#1 - #29, junk
#30: AppWindowToken{40bbc000 token=HistoryRecord{408cc260 com.site.android.conferencecompanion/.ProgramDates}}

...

#142: AppWindowToken{40ba65a8 token=HistoryRecord{40b93808 com.site.android.conferencecompanion/.ProgramSpeakers}}

Итак, если я правильно понимаю, что-то вроде 112 представлений хранится в памяти. Что я могу с этим поделать? Есть проверка или флаг или параметр, который я пропускаю? Я неправильно истолковал дамп?

Спасибо!

Ответы [ 7 ]

3 голосов
/ 01 июля 2011

Отличный способ проверить, откуда происходят утечки: если вы находитесь в Eclipse, выберите Window-> Open Perspecive -> DDMS, затем выберите запущенный процесс и выберите отслеживание распределения. Загрузите приложение, но НЕ прикоснитесь к приложению, прежде чем запускать трекер распределения.Затем сделайте то, что, по вашему мнению, вызовет проблему, а затем проверяйте распределение каждый раз.Это должно показать вам, какой именно код вызывает утечку.

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

1 голос
/ 30 августа 2012

(хотя это было год назад, я пришел сюда через Google)

Что-то подсказывает мне, что у вас загружено слишком много видов одновременно, и Android не может отследить их все. * Это звучало как неправильное использование ListView, в чем многие из нас виноваты. Предполагая, что у вас есть специальный адаптер массива:

public abstract View getView (int position, View convertView, ViewGroup parent)

Когда вы перегружаете эту функцию, всегда проверяйте convertView.

public abstract View getView (int position, View convertView, ViewGroup parent)
{
   View view = convertView;
   if ( view == null )
   {
      // create/inflate the view here
      // ex: view = inflater.inflate(R.layout.bob, null);
      // configure the static parts here
   }
   // configure the dynamic parts here

   return view;
}

Android имеет механизм «корзины» для представлений списка и будет использовать представления, если это возможно. Другими словами, вместо создания множества разных представлений, он будет извлекать старое представление из корзины.

В вашем случае у вас есть 10 различных видов просмотров. Если они очень похожи, вы можете создать суперпредставление и включить или отключить части представления (например, subView.setVisibility (View.GONE)). Просто остерегайтесь массивных блоков операторов. Я не использовал их раньше, но вы должны исследовать

public abstract int getItemViewType (int position)
public abstract int getViewTypeCount ()

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

  • Лично я не уверен на 100%, что это может быть, но у меня такое чувство, что есть вероятность 66%, что это
0 голосов
/ 29 июня 2016

В моем случае ошибка появилась, потому что я использовал класс Window, чтобы изменить цвет строки состояния, который поддерживается только в версиях сборки Android, которые старше 21. Добавьте следующее в ваш код, и это может работать

if(Build.VERSION.SDK_INT >= 21) {

//... your code with Window class here

}
0 голосов
/ 03 декабря 2013

У меня была такая же проблема, и я наконец решил ее.Решение:

Запустите ваше приложение из Eclipse и немного поиграйте с ним, постоянно наблюдая за LogCat-Console в Eclipse.При запуске нового занятия или чего-то подобного вы должны увидеть:

Tag:"WindowManagerImpl", Text:"addView, new view, mViews[1]:....".

Важная вещь здесь - mViews[x]-part.х говорит вам, сколько просмотров активно.Теперь, когда вы запускаете действие, но mViews-Counter сообщает вам, что у него 5-10 новых видов, вы можете быть уверены, что случайно создали слишком много видов.Таким образом, вы можете найти слабое место в вашем коде.

Это произошло в моем игровом приложении: каждый раз, когда я проигрывал игру, запускалось 5 или более новых GameOverActivities, потому что код, который запустил новую GameOverActivity, находился впетля.Таким образом, после нескольких минут игры 20 неиспользованных GameOverView съели мои ресурсы.(Так что будьте осторожны при запуске деятельности в циклах.)

0 голосов
/ 07 сентября 2013

Если я могу оставить здесь записку:

У меня были такие же журналы, когда я тестировал на Prestigo PMP5080B. Мое приложение также будет случайным образом заблокировано.

Я заметил, что когда я отсоединяю USB-кабель (достаточно отключить соединение с планшета, нажав в настройках), приложение работает нормально. Я также заметил, что, хотя я подключен к своему приложению с помощью Eclipse и через USB, SD-карта не может быть подключена, но я не знаю, связана ли эта проблема с моим приложением, поскольку я не храню на SD.

НТН

0 голосов
/ 04 мая 2012

Это проблема из Surface Flinger, который будет поддерживать и компоновать Surfaces of Application в устройстве отображения.

Попробуйте: уменьшите формат пикселя макета в XML-файле.

0 голосов
/ 04 июля 2011

Попробуйте расширить свои Действия, чтобы вы могли видеть, собирают ли они мусор (вызывается finalize ()). Аналогичным образом попробуйте расширить свои представления, чтобы определить, собирается ли их сборщик мусора.

Если вы помещаете Представления и Действия в Коллекции для кэширования, попробуйте использовать объекты коллекций, которые используют WeakReference, например WeakHashMap. Используете ли вы внутренние классы в своих представлениях или действиях? Если это так, эти классы содержат ссылку на Activity или View и предотвращают их сборку мусора. Хорошим примером является AsyncTask, который является внутренним классом. Эта задача выполняется в своем собственном потоке и может продолжать удерживать представления, даже если вы закрыли действие,

Кроме того, посмотрите на статические переменные, они держатся за объекты?

...