Записи с меткой: custom

Наступаем на грабли IDropInListItemRenderer

Иногда бывает необходимость получить доступ из рендерера к листу, в котором этот рендерер находится. Для этого необходимо заиплементить интерфейс IDropInListItemRenderer и затем взять поле owner у полученной на руки BaseListData. Это все будет прекрасно работать до тех пор, пока лист не окажется пустым:

        if (item is IDropInListItemRenderer)
        {
            if (data != null)
                IDropInListItemRenderer(item).listData = makeListData(data, itemToUID(wrappedData), 0);
            else
                IDropInListItemRenderer(item).listData = null;
        }

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

Реклама

, ,

Оставить комментарий

Профайлер памяти своими руками

Для флекса существует единственный полноценный профайлер — встроенный в Flex Builder. Для точной отладки он незаменим, однако в использовании несколько сложен и глючен, кроме того, для тяжелого проекта отладка начинает занимать очень много времени. Есть альтернативный профайлер — FlashPreloadProfiler. Какую-то полезную информацию он показывает, но подружиться с ним не удалось.

Именно для отладки тяжелого интранет приложения понадобилось придумать что-то простое, что позволило бы не теряя времени определять компоненты, которые вызывают утечки памяти и вести мониторинг приложения. И решение нашлось — flash.utils.Dictionary. Этот класс позволяет включить для ключей слабые ссылки (weak reference) через конструктор с параметром weakKeys=true:

var dict:Dictionary = new Dictionary(true);//weakKeys=true

Слабые ссылки не препятствуют сборке мусора, именно это свойство и можно использовать: подозрительные/проблемные объекты используем в качестве ключа:

dict[leaked_object] = UIDUtil.createUID();//Generates a UID (unique identifier); see mx.utils.UIDUtil

А полученный UID сохраняем в коллекцию:

var uids:ArrayCollection = new ArrayCollection();
uids.addItem(dict[leaked_object]);//save generated UID

В дальнейшем запустив таймер или используя setInterval мы пробегаем по ключам в dict (ключи со временем будут собираться сборщиком мусора) сравнивая значения по этим ключам (UID) с сохраненными в коллекции uids — получая возможность отслеживать работу сборщика мусора без профайлера:

        private function printDiff():void
        {
            var liveObjects:ArrayCollection = new ArrayCollection();//objects that were not collected
            for (var key:Object in references)
            {
                if (key != null)
                {
                    trace("Live object: ", uid, getQualifiedClassName(key));//print live object info
                    liveObjects.addItem(dict[key]);
                }
            }
            var removedObjects:ArrayCollection = new ArrayCollection();//objectes that were collected

            for each (var uid:String in uids)
            {
                if (!liveObjects.contains(uid))
                {
                    trace("Collected: ", uid); //print uid of collected object
                    removedObjects.addItem(uid);
                }
            }

            for each (var removedUID:String in removedObjects)
            {
                if (uids.contains(removedUID))
                {
                    uids.removeItemAt(uids.getItemIndex(removedUID));
                }
            }
            removedCodes.removeAll();//free memory
            liveObjects.removeAll();//free memory
        }

Необходимо также использовать хак (например из абзаца «Unsupported Way to Force GC» тут) для вызова сборщика мусора, иначе придется ждать некоторое время.

В таком виде уже можно по логам флешплеера установить объекты, которые могут вызывать утечки памяти (и уже точечно профайлить во Flex Builder), однако информация не очень удобна для восприятия. Для проекта я использовал более сложный вариант, написал визуальную часть с датагридом, автообновлением, сортировками, и еще парой тройкой удобных функций (выбор дисплейобъекта для мониторинга, добавление иерархии дисплейобъектов для монтиринга, копирование текущей иформации в буфер обмена). Исходники и рабочий пример я выложу в одном из следующих постов, так как надо причесать код :).

Окно профайлера

Окно профайлера

, , ,

3 комментария