[ruFlash] Загрузка картинки с width = 0 и height = 0

1 view
Skip to first unread message

Павел Гольцев

unread,
Dec 20, 2009, 6:43:51 PM12/20/09
to ruf...@googlegroups.com
Всем привет!
У кого-нибудь возникала такая проблема, когда после загрузки картинки
объект, который я достаю из content свойства объекта loaderInfo, имеет
width = 0 и height = 0?
У меня такая проблема периодически возникает в последнем проекте,
причем я никак не могу понять, почему это происходит.
В приложении происходит последовательная загрузка картинок разрешения
1024х768, причем этих картинок грузится около 100 друг за другом.
Список загрузки берется из хмл. В реале имеется всего 8 разных
картинок, и ссылки на них в хмл повторяются, в итоге получается список
из примерно 100 картинок (повторение сделано для теста, чтобы не
искать уникальных 100 картинок). Все картинки грузятся последовательно
и после загрузки добавляются в дисплей лист, хотя почти у всех
выставляется visible = false. И иногда получается так, что после
загрузки свойство content приходит в событие с нулевыми размерами и
все последующие загрузки тоже идут с нулями в свойствах размеров
(проверял trace'ом сразу в самом событии). Хотя эти же картинки по тем
же ссылкам, загруженные до этого момента, приходили с правильными
размерами. Причем такое бывает очень редко, но бывает. Плюс такое
начинает происходить постоянно, когда количество картинок
увеличивается раза в 2-3. У меня сложилось впечатление, что приложению
просто не хватает выделенной памяти. Такое может быть? Может во флэше
есть какое-то ограничение на общее количество загруженной графики?
Бред конечно, но я уж и не знаю, что думать. Насколько мне известно,
если приложению не хватает памяти, процесс запрашивает у операционной
системы ее дополнительно и если в ОС ее не хватает, включается система
свопинга и памяти по сути должно хватать всегда.
Кто-нибудь знает, как с этим можно справиться?

Uncle Sam

unread,
Dec 21, 2009, 5:47:42 AM12/21/09
to ruFlash
Если кто знает откуда ноги растут - поделитесь, мне тоже интересно )
В текущем проекте тоже столкнулся с подобной проблемой, но на
картинках меньшего размера. Правда, "ограничение" даёт о себе знать
только в случае с количеством картинок от 150-200. В моём случае
решением проблемы стало внушение пользователям, что не надо пихать
целиком всю папку с картинками в приложение (благо, разработка для
внутреннего использования) =)
Но по ощущениям да, есть какое-то ограничение на объём занимаемой
памяти...

Flop Serg

unread,
Dec 21, 2009, 6:03:23 AM12/21/09
to ruflash
Но по ощущениям да, есть какое-то ограничение на объём занимаемой
памяти...


нет такого ограничения можешь провести простой тест

vat temp:String = "Temp";
for (var i:int=0 ; i<100; i++) {
   temp += temp;
}

и диспетчером задач проверить сколько памяти отожрет флешлеер

Eugene Zatepyakin

unread,
Dec 21, 2009, 6:09:44 AM12/21/09
to ruf...@googlegroups.com
Ограничение есть везде и всегда к сожалению:

http://www.quasimondo.com/archives/000691.php

Flop Serg

unread,
Dec 21, 2009, 6:14:06 AM12/21/09
to ruflash
Ограничение есть везде и всегда к сожалению:



ну это ограничение системы
адресное пространство процесса - 32 бита

Alexey Taran

unread,
Dec 21, 2009, 6:18:24 AM12/21/09
to ruf...@googlegroups.com
А картинки грузятся все скопом или последовательно? Может ограничить
количество одновременно загружаемых?

Павел Гольцев

unread,
Dec 21, 2009, 11:18:16 AM12/21/09
to ruf...@googlegroups.com
А картинки грузятся все скопом или последовательно? Может ограничить
количество одновременно загружаемых?

Я же писал, что последовательно. Дело не в одновременно загружаемых потоках данных, это однозначно. Да и сделал последовательно специально, поскольку чем быстрее загрузится первая картинка, тем быстрее приложение станет доступно пользователю для взаимодействия. Поэтому дело тут не в количестве одновременно загружаемых потоков.
Кол-во системной памяти опять же тут непричем. У меня на машине 4 гига оперативной памяти, неужели какие-то жалкие 200 картинок могли слопать такое количество памяти...
У кого-нибудь есть еще идеи?

bartleby

unread,
Dec 21, 2009, 11:21:30 AM12/21/09
to ruFlash
приведите пример кода всей последовательности загрузки картинок...
очень сложно что-то сказать не видя кода.

Павел Гольцев

unread,
Dec 21, 2009, 12:41:32 PM12/21/09
to ruf...@googlegroups.com
приведите пример кода всей последовательности загрузки картинок...
очень сложно что-то сказать не видя кода
 
Я не думаю, что дело в коде, поскольку такая проблема возникла не только у меня одного.
Функция-инициатор загрузки находится в классе, который является контейнером для объектов типа PagePreviewItem, наследуемых от Sprite

// Функция-инициатор

protected function createItems(data_list:XMLList, create_first_single_page:Boolean):void {
            cleanAndRemoveContent();
           
            if (data_list.length() == 0) return;
           
            _cont = new Sprite();
            _cont.x = ST_X;
            addChild(_cont);
           
            var first_page:PagePreviewItem;
           
            var clp:PagePreviewItem;
            var num:uint = Math.min(Math.ceil(create_first_single_page ? (data_list.length() - 1) / 2 + 1 : data_list.length() / 2), MAX_ITEMS);
            var i:uint = 0;
            var x_pos:uint = 0;
            while (num--) {
                if (i == data_list.length() - 1 ||
                    create_first_single_page) {
                    clp = new SinglePagePreviewItem();
                   
                    create_first_single_page = false;
                } else {
                    clp = new DoublePagePreviewItem();
                    DoublePagePreviewItem(clp).initPage2(data_list[i + 1].thumb);
                }
               
                if (!first_page) first_page = clp;
               
                SinglePagePreviewItem(clp).initPage1(data_list[i].thumb);
               
                clp.x = x_pos;
                initItem(clp);
               
                x_pos += clp.width + X_OFFSET;
               
                i++;
               
                if (clp is DoublePagePreviewItem) i++;
            }
           
            SinglePagePreviewItem(first_page).loadPreview();
        }

// инит созданного клипа
protected function initItem(clp:PagePreviewItem):void{
            clp.visible = false;
            _cont.addChild(clp);
               
            clp.addEventListener(Event.COMPLETE, itemLoadCompleteHandler, false, 0, true);
        }

// выполняется после того, как текущая картинка загрузилась, и инициирует загрузку следующей картинки из контейнера _cont
protected function itemLoadCompleteHandler(e:Event):void {
            e.target.removeEventListener(Event.COMPLETE, itemLoadCompleteHandler);
           
            if (!_cont) return;
           
            if (_cont.contains(DisplayObject(e.target))) {
                if (!_showup_timer.running &&
                    _showing) {
                    animateCurItem();
                }
               
                var ind:uint = _cont.getChildIndex(DisplayObject(e.target));
                if (ind == _cont.numChildren - 1) {
                    dispatchEvent(new Event(Event.COMPLETE));
                } else {
                    var clp:SinglePagePreviewItem = SinglePagePreviewItem(_cont.getChildAt(ind + 1));
                    clp.loadPreview();
                }
            }
        }

Вкратце, в цикле создаются объекты типа SinglePagePreviewItem и DoublePagePreviewItem. Оба наследуются от класса PagePreviewItem, причем SinglePagePreviewItem наследуется от PagePreviewItem напрямую, а DoublePagePreviewItem наследуется уже от SinglePagePreviewItem. В конце функции для самого первого элемента цикла стартует загрузка картинки при помощи функции loadPreview.

// Функция класса SinglePagePreviewItem выглядит так
public function loadPreview():void {
            PreviewCont(cont.p1).loadImg(_p1_url);
        }

// Функция класса DoublePagePreviewItem выглядит так
public function loadPreview():void {
            super.loadPreview();
           
            PreviewCont(cont.p2).loadImg(_p2_url);
        }

// В этих функциях объекты p1 и p2, которые располагаются в мувике cont, являются объектами типа PreviewCont. Функция загрузки loadImg для PreviewCont выглядит так
public function loadImg (url:String, retry_cnt:uint = 2):void {
            if (url) {
                if (_url == url) return;
               
                _url = url;
            }
           
            if (_url) {
                _load_retry_cnt = retry_cnt;
               
                loadImage();
            }
        }

// Функция loadImage с модификатором protected выглядит так
protected function loadImage ():void {
            _ldr.load(new URLRequest(_url));
               
            showLdr();
        }

Здесь _ldr - объект типа Loader, который создается в конструкторе класса PreviewCont таким образом
_ldr = new Loader();
          _ldr.contentLoaderInfo.addEventListener(Event.INIT, initHandler, false, 0, true);
            _ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler, false, 0, true);
            _ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);

// А обработчик initHandler выглядит так
protected function initHandler (evt:Event):void {
            var clp:Bitmap = evt.target.content;
           
            clp.smoothing = true;
            clp.x = _rect_x;
            clp.y = _rect_y;
            clp.width = rect.width;
            clp.height = rect.height;
           
            _ldr.unload();

// здесь я ставлю trace(clp.width, clp.height)
trace(clp.width, clp.height)
           
            removeChildAt(0);
            addChildAt(clp, 0);
           
            hideLdr();
           
            dispatchEvent(new Event(Event.COMPLETE, true));
        }

Код старался привести только необходимый, если что-то еще нужно или непонятно, пишите, допишу и дозакину.

В итоге в трейсе в последней приведенной функции при описанных обстоятельствах после корректных размеров начинает в каком-то месте вылезать 0 0. Это все происходит при описанных условиях. Причем если количество картинок небольшое (меньше 100-80), то все вроде как работает без ошибок. При увеличении количества картинок начинаются описанные выше проблемы.
Неужели никто не в состоянии помочь или хотя бы что-то посоветовать?

Flop Serg

unread,
Dec 21, 2009, 12:46:20 PM12/21/09
to ruflash
Неужели никто не в состоянии помочь или хотя бы что-то посоветовать?

не грузи по 200 картинок а грузи по +- 10 от того места на которое смотрят
не может же юзер одновременно видеть 200 картинок

Павел Гольцев

unread,
Dec 21, 2009, 12:49:39 PM12/21/09
to ruf...@googlegroups.com
последний вызов идет без параметра bubble = true, то есть так
dispatchEvent(new Event(Event.COMPLETE));
Я упростил код, чтобы не загромождать написанное. Я не стал писать вышестоящие обработчики, которые проверяют загрузку одной картинки для SinglePagePreviewItem и двух для DoublePagePreviewItem и уже далее генерируют событие Event.COMPLETE, которое и улавливается классом PagePreviewItem. Упрощение абстрактное с целью показать, что и куда идет

Павел Гольцев

unread,
Dec 21, 2009, 12:52:48 PM12/21/09
to ruf...@googlegroups.com

не грузи по 200 картинок а грузи по +- 10 от того места на которое смотрят
не может же юзер одновременно видеть 200 картинок
 
 Дело в том, что хотелось бы в моменты простоя канала на стороне пользователя использовать его, загружая картинки, которые так или иначе могут быть загружены впоследствии. А если следовать твоему совету, то при каждом переходе на 10 картинок вперед придется инициировать загрузку и выводить загрузчики, что заставляет пользователя ждать. При моем подходе вероятность того, что ему придется ждать, меньше. Но возникают непонятные проблемы, которые я не мог предвидеть в начале разработки.

Павел Гольцев

unread,
Dec 21, 2009, 12:58:04 PM12/21/09
to ruf...@googlegroups.com
Может кто-то что-то еще посоветовать? Очень неохота переписывать приложение из-за какого-то непонятного глюка.

Mihail Savinov

unread,
Dec 21, 2009, 1:30:50 PM12/21/09
to ruf...@googlegroups.com
О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫:

>
> _ldr.contentLoaderInfo.addEventListener(Event.INIT,
> initHandler, false, 0, true);
> <http://groups.google.com/group/ruFlash/web/rules>


О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ height+width О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ COMPLETE, О©╫О©╫О©╫О©╫О©╫О©╫ INIT ?

Ivan Dembicki

unread,
Dec 21, 2009, 2:03:20 PM12/21/09
to ruf...@googlegroups.com
Hello Павел,

> Может кто-то что-то еще посоветовать? Очень неохота переписывать приложение
> из-за какого-то непонятного глюка.

- совет простой: на событие INIT создай событие onEnterFrame и в
первом же срабатывании прибей его. Только после этого начинай работать
с картинкой.


--
iv
http://www.bezier.ru
http://bezier.googlecode.com

andrey Vichodcev

unread,
Dec 22, 2009, 9:50:53 AM12/22/09
to ruf...@googlegroups.com
width height вообще странно работают.
вот только недавно узнал, что если объект повернуть, то width heigh
трасироваться у него будут как область в которую он вписан.

тяжело читать предложенный код.

clp.width = rect.width;
clp.height = rect.height;

ты сам устанавливаешь ширину и высоту???

andrey Vichodcev

unread,
Dec 22, 2009, 9:52:54 AM12/22/09
to ruf...@googlegroups.com
хотя если проблема только после 100-й картинки, то скорей всего
загруженная картинка просто не успевает пихаться в память.

Павел Гольцев

unread,
Dec 22, 2009, 10:04:09 AM12/22/09
to ruf...@googlegroups.com
> тяжело читать предложенный код.

почему, объясните. Постараюсь исправиться

 
ты сам устанавливаешь ширину и высоту???

Да... Возможно, я не там трейс поставил в приведенном тут коде. Когда тестил, он наверняка стоял выше, до изменения размеров. Хотя может и так стоял, но поскольку какие-то проблемы с загрузкой клипа, то даже такое присвоение скорее всего ничего не меняет.
А размеры я меняю для того, чтобы подогнать под определенный прямоугольник, который служит для позиционирования и растяжения картинки, как направляющий. Этот клип статичный, лежит на таймлайне, и размеры у него постоянные. Так что он точно с ненулевыми размерами.



Mihail Savinov

unread,
Dec 22, 2009, 10:20:41 AM12/22/09
to ruf...@googlegroups.com
О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫:
> > О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫.
>
> О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫. О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫
> <http://groups.google.com/group/ruFlash/web/rules>
О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ rect = О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ Rectangle, О©╫
О©╫О©╫О©╫ "clp" = "О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫" :)))
О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ - О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫)

--
Mihail Savinov

Sergey Kruk

unread,
Dec 22, 2009, 10:23:25 AM12/22/09
to ruf...@googlegroups.com
У меня была такая ситуация в некоторых браузерах и некоторых версиях
плеера, когда я грузил картинку из другого домена. Наличие
crossdomain.xml не спасало. Вылечилось так:

Заменить _ldr.load(new URLRequest(_url)); на

_ldr.load(new URLRequest(_url), new LoaderContext(true));

Смысл этого знака судьбы я расшифровал так, что при загрузке
изображений по умолчанию не проверяется crossdomain.xml, при этом
ширина и высота изображения считаются свойствами объекта из другой
песочницы и не выводятся. А интернет эксплорер некоторых версий даже
картинку не показывал.

При одновременном наличии crossdomain.xml и контекста загрузчика,
которому велено этот файл проверить, ошибка больше не появлялась.

Сергей Крук

Reply all
Reply to author
Forward
0 new messages