#apache-flex #memory #datagrid #itemrenderer #flex-spark
#apache-flex #память #datagrid #itemrenderer #flex-spark
Вопрос:
У меня вопрос о Spark DataGrid и о том, как это работает с точки зрения сборки мусора. Я обнаружил, что если я динамически добавляю и удаляю столбцы из DataGrid во время выполнения, GridColumns и itemRenderers никогда не освобождаются из памяти.
Например, если у меня есть список из 10 элементов, и я создаю 10 столбцов, в нем будет 100 идентификаторов элементов и 10 столбцов сетки. Если я удалю все столбцы, они все еще будут там.
Если я добавлю 5 столбцов обратно, похоже, что не создается больше экземпляров GridColumns или itemRenderers — в памяти все еще остается 100 средств визуализации и 10 столбцов.
Этого не происходит с сеткой данных MX. Поскольку столбцы удаляются, элементы отображения и DataGridColumns освобождаются из памяти, когда я смотрю на профилировщик впоследствии, я вижу 0 элементов отображения и 1 столбец DataGridColumn.
У кого-нибудь есть какие-либо идеи о том, что здесь будет происходить? Или я просто что-то упускаю?
Вот код, который я использовал для тестирования Spark DataGrid:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<s:ArrayList id="dp">
<fx:Object label="label 1"/>
<fx:Object label="label 2"/>
<fx:Object label="label 3"/>
<fx:Object label="label 4"/>
<fx:Object label="label 5"/>
<fx:Object label="label 6"/>
<fx:Object label="label 7"/>
<fx:Object label="label 8"/>
<fx:Object label="label 9"/>
<fx:Object label="label 10"/>
</s:ArrayList>
<s:ArrayList id="columns">
<s:GridColumn dataField="label"/>
</s:ArrayList>
</fx:Declarations>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:DataGrid dataProvider="{dp}" columns="{columns}" width="100%" height="100%"/>
<s:HGroup>
<s:Button label="Add Column" click="columns.addItem(new GridColumn('label'))"/>
<s:Button label="Remove Column" click="if( columns.length > 0 ) columns.removeItemAt(0)"/>
</s:HGroup>
</s:Application>
Комментарии:
1. «если у меня есть список из 10 элементов с 10 элементами, и я создаю 10 столбцов, будет 100 itemRenderers»; это верно только в том случае, если ваша DataGrid отображает 10 строк. Если вы используете DataGrid, отображается 5 строк; тогда у вас есть 50 элементов для отображения. [Примечание: Я не уверен, создает ли Spark DataGrid все столбцы одновременно, как это делает MX DataGrid; если это не так, у вас может быть еще меньше средств визуализации; в зависимости от количества отображаемых столбцов)
2. 1 за предоставление полного, пригодного для выполнения примера.
Ответ №1:
У меня еще не было возможности просмотреть код сетки данных Flex 4.5, но я бы предположил, что они используют объединение объектов для средств визуализации элементов.
В сетке данных главное — скорость, и обычно больше всего времени занимают средства визуализации элементов (особенно создание экземпляров). Чтобы поддерживать скорость работы DataGrid, они не «уничтожают» средства визуализации элементов сразу. Они будут храниться в течение x времени; или для некоторых алгоритмов объединения объектов никогда не освобождайте их. Проще просто сохранить их в памяти, поскольку они изначально не должны быть огромными и имеют более быструю динамическую сетку данных.
На самом деле, я быстро поискал в Google, и я был прав:
Все эти части оболочки DataGrid IFactory должны быть IVisualElements. Во многих случаях это просто графические элементы, такие как прямоугольники или линии, которые могут быть визуализированы довольно эффективно, потому что поддержка «совместного использования объектов отображения» в среде Flex runtime использует один DisplayObject для отображения их всех. Как и средства визуализации элементов, эти визуальные элементы объединяются во внутренний пул и перерабатываются повторно, чтобы избежать затрат на их создание и добавление при прокрутке сетки данных.
Похоже, что средства визуализации элементов объединены не только внутри каждой сетки данных, но и для всех сеток данных. Должен сказать, очень хорошая практика. И поверьте мне, это очень полезно для производительности Flex на DataGrids.
Ответ №2:
Я полагаю, что ответ на ваш вопрос заключается в свойстве «useVirtualLayout».
Вместо создания средства визуализации элементов для каждого дочернего элемента вы можете настроить контейнер на использование виртуального макета. При виртуальном макете контейнер повторно использует средства визуализации элементов, так что > он создает средства визуализации элементов только для видимых в данный момент дочерних элементов контейнера. Когда дочерний элемент удаляется с экрана, что возможно путем прокрутки контейнера, новый дочерний элемент, прокручиваемый на экране, может повторно использовать средство визуализации своего элемента.
Чтобы настроить контейнер на использование виртуального макета, установите для свойства useVirtualLayout значение true для макета, связанного с контейнером. Виртуальную компоновку поддерживает только DataGroup или SkinnableDataContainer с макетом, установленным в VerticalLayout, HorizontalLayout или TileLayout. Подклассы макета, которые не поддерживают виртуализацию, должны предотвращать изменение этого свойства»
Редактировать: Только что выяснил, что DataGrids поддерживают только виртуальные схемы, поскольку использует пользовательскую «сеточную схему». Так что, возможно, это не ответ на ваш вопрос.