2013-03-06 4 views
9

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

У меня есть RelativeLayout, который заполнен динамически. В основном приложение загружает поток форума в XML, а затем отображает дерево обсуждений, поэтому каждое сообщение отображается в собственной группе представлений. Я решил не использовать WebView, потому что я хочу реализовать некоторые функции на стороне клиента, которые должны быть проще выполнять на пользовательских представлениях, чем на HTML-странице.

Однако этот подход имеет серьезный недостаток: он тяжелый.

Первая проблема (я решил) - nesting of views. Теперь это не проблема, мой макет почти плоский, поэтому максимальная глубина 10-12 (с самого верха PhoneWindow $ DecorView, фактическая глубина зависит от данных).

Теперь я достиг следующего предела, который каким-то образом связан с (или вызванным) потреблением ресурсов видами. После загрузки данных приложение некоторое время зависает для создания макета (создает представления и заполняет их данными), и время зависания, похоже, растет линейно с размером данных; и если данные достаточно велики, представление никогда не появится (в конечном итоге система предлагает закрыть приложение, потому что оно не отвечает).

Теперь вопросы:

  1. потребление памяти незначительно зависит от класса представления? Другими словами, существует ли какая-либо существенная разница между Button и TextView, или ImageView? Я могу прикрепить обработчик кликов к любому виду, чтобы они не сильно отличались в использовании.

  2. Действительно ли фоновые изображения влияют на производительность? Если одно и то же изображение установлено в N просмотрах, сделает ли оно макет N раз тяжелее? (Я понимаю, что этот вопрос может выглядеть глупым, но в любом случае.)

  3. Изображения с девятью патчами значительно тяжелее обычных? Что лучше: создать N виды, где у каждого есть некоторые фоновые изображения, или сделать один вид N раз шире и имеет повторяющийся фон?

  4. Учитывая некоторые макеты, что должно быть оптимизировано в первую очередь: общее количество просмотров, уровней вложенности или что-то еще?

  5. Самое интересное. Возможно ли измерить или, по крайней мере, оценить ресурсы, потребляемые деятельностью и ее мнениями? Если я внесу некоторые изменения, как я могу увидеть, что я иду по правильному пути?

UPDATE

Благодаря User117, некоторые вопросы, которые задавали мне выше, теперь ответил. Я использовал средство просмотра иерархии и оптимизировал свой макет: по сравнению с тем, что у меня было раньше, общее количество просмотров теперь уменьшено почти в два раза, а также вложенность.

Однако приложение все еще висит на большой ветке форума.

UPDATE 2

Я подключен отладчик на устройство и обнаружил, что приложение получает из памяти.

Но для меня очень неожиданно возникает ошибка после заполнения макета. Последовательность выглядит следующим образом:

  1. Все мои взгляды добавлены. Я вижу небольшое замедление, поскольку они добавляются.
  2. Почти ничего не происходит в течение пары секунд. За это время в журнале генерируется несколько информационных сообщений, они идентичны: [global] Loaded time zone names for en_US in XXXXms, единственное различие - это количество миллисекунд.
  3. Появляется сообщение об ошибке из памяти: [dalvikvm-heap] Out of memory on a N-byte allocation (действительный размер варьируется). Начинается длинная отчетность об ошибках.

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

UPDATE 3

Наконец я нашел основной вопрос. Вот скриншот из моего приложения, см. Объяснение ниже изображения.

A tree-like hierarchy of messages.

Каждое сообщение состоит из круглой кнопки, которая показывает или скрывает ответы и красный содержимого кадра справа от кнопки. Это очень просто и требует только 6 просмотров, включая макеты.

Проблема заключается в отступе с этими линиями связи, которые показывают, какое сообщение связано с которым.

В моей текущей реализации отступ состоит из небольших ImageView, каждый из которых содержит квадратное изображение, которое показывает либо пустое пространство, либо вертикальную линию, или T-образный разъем, либо L-подобный угол. Все эти представления выравниваются друг с другом в пределах большого RelativeLayout, который содержит все дерево обсуждений.

Это прекрасно работает для небольших и средних деревьев (до нескольких сотен сообщений), но когда я пытаюсь загрузить большое дерево (сообщения 2K +), я получаю результат, описанный в ОБНОВЛЕНИИ 2 выше.

Очевидно, у меня есть две проблемы. Я создаю большое количество просмотров, которые все потребляют память, и эти представления - это ImageView, для которых требуется больше памяти для рендеринга, поскольку они визуализируют растровое изображение и, следовательно, создают графические кеши (в соответствии с объяснением, данным User117 в комментариях).

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

Моя другая идея состояла в том, чтобы создать изображение с отступом для каждого сообщения, которое будет содержать все трубы и углы, поэтому каждое сообщение будет иметь единственный отступ в виде вместо 10 или 20. Но это еще более утомительно: у меня есть вне памяти в середине заполнения макета. (Я кэшировал изображения на карте, поэтому не было создано двух растровых изображений с одинаковой последовательностью изображений, что не помогло.)

Итак, я прихожу к выводу, что я в тупике. Можно ли сразу рисовать все эти строки?

ответ

7
  1. Различные View «s разные виды объекта. Некоторые только draw() легкий материал, некоторые могут содержать большие объекты Bitmap, а также объекты-обработчики и т. Д. Итак, да разные View будут потреблять разный объем оперативной памяти.

  2. Если один и тот же объект Bitmap является общим для представлений, в ОЗУ имеется только один объект, каждый вид будет иметь ссылочную переменную, указывающую на этот объект. Но не так, когда View draws: Рисование же Bitmap n раз в n местах на экране будет потреблять n раз CPU и генерировать n разных bitmap_cache для каждого вида.

  3. Каждая сторона изображения с 9 патчами на самом деле больше на 2 пикселя от исходного изображения. Они не сильно отличаются друг от друга как файл. Когда они нарисованы, их можно масштабировать и займет почти равное пространство. Единственное отличие состоит в том, что 9-патч масштабируются по-разному.

    1. Установка фона более крупного родительского представления лучше, когда детские представления прозрачны, а фон будет отображаться.

    2. Вы можете сохранить небольшое изображение и установить плиточный фон, чтобы он мог заполнить большую площадь.

  4. Верстка должна быть оптимизирована первым, потому, что все представления могут быть не видны в данный момент времени, скажем лишь несколько просмотры видны при прокрутке раскладки. Затем вы можете сократить общее количество просмотров. Возьмите реплики от ListView: Учитывая, что пользователь будет видеть только подмножество общих данных за раз, он перепрограммирует представления. и экономит много ресурсов.

  5. SDK обеспечивает Иерархия Viewer инструмент для этой цели. Он показывает полную древовидную структуру работающего макета, а также помещает красные флаги для вялых частей макета.

Хорошая планировка то, что:

  1. Легко быть измерена (избегать сложных взвешенных ширины, высоты и выравнивания). Для примера вместо layout_gravity="left" для каждого ребенка, родитель может иметь gravity="left".

  2. Имеет меньшую глубину, каждый перекрывающий вид добавляет еще один слой для компоновки во время рисования экрана. Каждая вложенная структура просмотра запрашивает вызов с цепочкой.

  3. Умный и перепрограммирует вид, а не создает все из них.

  4. Повторно использует свои детали: теги наподобие <merge> и <include>.

Update: Ответов на this question, показывает множество подходов к древовидному в андроид.

+0

Учитывая простую функцию: кнопка с графикой, которая имеет действие OnClick, я мог бы пойти несколько путей: 1) вставить 'Button' с фоновым изображением, 2) вставляет' ImageView', 3) вставить 'TextView ', а затем назначить обработчик кликов этому объекту, независимо от того, какой класс используется. Есть ли разница в производительности среди этих способов? –

+0

@AlexanderDunaev Ну, 'Button' будет использовать визуальные эффекты ОС по умолчанию,' ImageView' загрузит немного больше от вас ресурсов приложения, и 'TextView' содержит дополнительный код измерения/рендеринга текста, а также один и тот же код обработчика прилагается. _индивидуальная разница в временах, полученных этими представлениями для управления/повторного рисования, была бы неуместной. Теперь, если у вас есть около тысячи из них в вашем макете, то общие различия могут быть значительными. Кроме того, 'Button',' ImageButton', 'ImageView',' TextView' и т. Д. Являются _built для конкретной цели и лучше всего подходят для этой цели. –

+1

I второй @ User117 ответ, особенно пункт 4). Не создавайте представления в возможно длинных (иерархических) списках, которые не видны. Вместо этого измените * содержимое * видений, которые видны, путем «прокрутки» данных, которые они содержат в представлении, подобно тому, как ListView и связанные с ним представления. Например. в вашем скриншоте, не более 11 или 12 строк должны быть созданы, каждый из которых содержит родительское-представление, изображение ракурс и текстовый вид с некоторым пользовательским рисунком (линия) л. В целом, не более 36 просмотров в этом случае. –