Вход

Просмотр полной версии : visible=0/1 vs add/removeChild


cauchy
11.11.2009, 18:11
Сейчас занимаюсь переделкой одного проекта и возник такой вопрос:
надо отображать в одном спрайте различные формы. Какие плюсы и минусы у каждого из озвученных выше подходов (присваивать visible неактивной формы нулю или удалять её из списка отображаемых объектов)?
Насколько я понимаю минус visible=0 в том что всё равно память хавается. Хотя поидее и при removeChild она тоже будет хаваться, если только не удалить все все ссылки на неактивную форму (а все все ссылки в моём случае не получиться наверное удалить).
Минус removeChild лично для меня в том, что при попытке удалить ненужную форму, если она уже была удалена ранее, вылетает ошибка, в то время как visible = 0 никаких ошибок не вызывает само собой. Хотя надо стремиться к тому, чтобы таких ошибок небыло впринципе, сейчас мне легче работать с visible.
Есть ли ещё какие-то другие различия между этими подходами?

relevance4
11.11.2009, 19:50
это два абсолютно разных метода, они не являются альтернативами друг-другу.

перед использованием removeChild можно делать проверку, чтобы не возникала ошибка.

mayakwd
11.11.2009, 22:42
проверка о которой написано выше
if (formToDelete != null && formContainer.contains(formToDelete))
formContainer.removeChild(formToDelete);

bicubic_bublic
12.11.2009, 01:01
если имеется МувиКлип с анимацией или что-то перерисовываемое динамически, то visible = false не отменяет прорисовку каждого его кадра, однако если убрать из дерева отображения, то прорисовка просчитываться для этого объекта не будет.

Artic
12.11.2009, 01:53
я делаю так


if (getChildByName("super")) removeChild(super)
super = new Sprite();
super.name = "super";
addChild(super);

bicubic_bublic
12.11.2009, 01:55
я делаю так


лихо вы ключевое слово используете

SamFR
12.11.2009, 02:28
Arctic, не лучший метод. Не говоря уже о super =)

Artic
12.11.2009, 02:37
^^ super не всмысле super() а в смысле я тут в пример просто написал ^^

почему не лучший способ ? собственно всегд волновал вопрос нормального удаления контейнера перед его пересозданием и выходом нашел, name, собственно работает без ошибок, недостатков кроме задания каждому контейнеру name, нету или я ошибаюсь ?

AL.exe
12.11.2009, 02:53
проверка о которой написано выше
if (formToDelete != null && formContainer.contains(formToDelete))
formContainer.removeChild(formToDelete);

Проще try...catch

bicubic_bublic
12.11.2009, 02:55
if (formToDelete.parent) {
formToDelete.parent.removeChild(formToDelete);
}

Artic
12.11.2009, 03:03
try
{
removeChild(sameContainerMbNotOnstage)
}
catch(error:Error)
{
}

то есть так правильно будет ?

AL.exe
12.11.2009, 03:08
if (formToDelete.parent) {
formToDelete.parent.removeChild(formToDelete);
}

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

Вообще не понятно зачем все это, есть есть try..catch)

Добавлено через 1 минуту

try
{
removeChild(sameContainerMbNotOnstage)
}
catch(error:Error)
{
}

то есть так правильно будет ?

Я бы поставил ArgumentError вместо Error

bicubic_bublic
12.11.2009, 03:17
Ну, так как с самого начала темы была задана параноидальность в плане ошибок, то здесь не учитывается, что formToDelete может быть null.

я так понял что formToDelete существует, просто неизвестно присутствует ли..
ну а в более параноидальном случае, почему бы и не:

if(formToDelete && formToDelete.parent) {
formToDelete.parent.removeChild(formToDelete);
}

mayakwd
12.11.2009, 03:24
способов море, письками меряться будем?
я бы вообще в любом случае написал
if (formToDelete && !formToDelete.destroyed)
formToDelete.destroy();

derhab
12.11.2009, 08:27
if (formToDelete && !formToDelete.destroyed)
formToDelete.destroy();
if(formToDelete && formToDelete.parent) {
formToDelete.parent.removeChild(formToDelete);
}
в обоих этих случаях вылетит ошибка если formToDelete == null
try..catch - универсальный метод, зачем изобретать велосипед

mayakwd
12.11.2009, 08:31
в обоих этих случаях вылетит ошибка если formToDelete == null
try..catch - универсальный метод, зачем изобретать велосипед

подумайте еще раз.

derhab
12.11.2009, 09:04
подумайте еще раз.
хотите сказать что при formToDelete == null не будет ошибки?

mayakwd
12.11.2009, 09:08
public class Test extends Sprite {
private var formToDelete : Object = null;
public function Test() {
if (formToDelete) {
trace ("существует");
} else {
trace ("не существует, но ошибки к вашему сожалению тоже не будет");
// throw new Error("formToDelete == null");
// если очень хочется - раскомментить строчку выше.
}
}
}

derhab
12.11.2009, 09:19
public class Test extends Sprite {
private var formToDelete : Object = null;
public function Test() {
if (formToDelete) {
trace ("существует");
} else {
trace ("не существует, но ошибки к вашему сожалению тоже не будет");
// throw new Error("formToDelete == null");
// если очень хочется - раскомментить строчку выше.
}
}
}
ну тут очевидно)

я ошибся, смутило то что тут
if(formToDelete && formToDelete.parent)
происходит обращение к к свойству несуществующего объекта...

mayakwd
12.11.2009, 09:24
во флэш используется сокращенная логика
при условии
if (formToDelete && formToDelete.parent)
если первое условие будет false второе условие не проверяется.

cauchy
12.11.2009, 10:54
если имеется МувиКлип с анимацией или что-то перерисовываемое динамически, то visible = false не отменяет прорисовку каждого его кадра, однако если убрать из дерева отображения, то прорисовка просчитываться для этого объекта не будет.

Точно, как то не подумал об этом. Но впринципе в данном конкретном случае это не важно.
За всевозможные варианты всем спасибо. Вчера тоже увидел в другом месте удаление через try и catch, до этого что-то и не догадывался о таком способе (не считая первоначального обучения, сам ещё ни разу не использовал try/catch :rolleyes:)
Но в этом проекте наверное пока оставлю через visible, там ещё других проблем ой-ой-ой :confused:

Smrad
12.11.2009, 11:31
visible = false отменяет перерисовку. Не знаю, откуда вы взяли обратное, но по тесту производительности это очень хорошо видно.

Помещать removeChild в try можно только в том случае, если аргумент removeChild'а никогда не будет равен null, как это ни странно звучит. В том смысле, что можно подстраховаться от краша обработав исключение, а использовать исключения в логике программы неграмотно и медленно. Исключения работают быстро, только если они не происходят :).

bicubic_bublic
12.11.2009, 11:43
visible = false отменяет перерисовку. Не знаю, откуда вы взяли обратное, но по тесту производительности это очень хорошо видно.


"show redraw regions" говорит об обратном

Felicast
12.11.2009, 12:06
Вчера тоже увидел в другом месте удаление через try и catch, до этого что-то и не догадывался о таком способе
забудьте об этом способе. лучше предотвратить исключение, чем весь код обрамлять try catch

switcher!
12.11.2009, 13:14
если имеется МувиКлип с анимацией или что-то перерисовываемое динамически, то visible = false не отменяет прорисовку каждого его кадра, однако если убрать из дерева отображения, то прорисовка просчитываться для этого объекта не будет.
на чем основана эта информация? есть ссылки на теорию или еще какие-то доказательства?
Тоже интересовал этот вопрос. Нашел комп послабже моего и сделал тест, в котором:
- динамически дабавил в дисплей лист 5000 спрайтов с приличными размерами.
- далее через Timer сделал fps равное примерно 1000 в секунду (по номиналу).
- на каждом "кадре" все спрайты меняли координаты.

Сперва для всех спрайтов visible поставил в false и потестил. Результат для 200-т "кадров" - 1300 милисекунд. Затем поставил visible = true... В общем для 1-го "кадра" результат - 8100 примерно.
Крайне сомнительно, что с visible = false отрисовка происходит.

Однако, тот же тест, но без добавления спрайтов в дисплей лист действительно показал незначительный, но стабильно более быстрый результат. Соответственно, я педположил, что "разница" вызвана самим фактом нахождения в дисплэй-листе нежели значением visible.

Тем не менее я основываюсь на результатах теста, а не на теории. И возможно где-то ошибаюсь в рассуждениях. Если так, то где :)

UPD:
"show redraw regions" говорит об обратном
а у меня "show redraw regions" не показывает отрисовку спрайтов.

derhab
12.11.2009, 13:33
"show redraw regions" говорит об обратном
"show redraw regions" не работает для объекта с visible = false

Волгоградец
12.11.2009, 14:18
А у меня показывает отрисовку. Клипов.

Smrad
12.11.2009, 14:21
"show redraw regions" говорит об обратном
Упрямая штука тесты. Я даже не могу представить, как плеер будет рисовать объекты у которых visible стоит в false, с нулевой альфой шоле? Нет, глупость, конечно. :)

derhab
12.11.2009, 14:40
А у меня показывает отрисовку. Клипов.
очень интересно)) а у меня нет
можно пример?

switcher!
12.11.2009, 14:49
я бы тоже посмотрел пример с клипами, с visible = false -)

Волгоградец
12.11.2009, 15:12
Эммм. Создаю клип с анимацией --> кидаю на сцену --> запускаю --> правой кнопкой выбираю show redraw regions. Вуаля.

switcher!
12.11.2009, 15:49
я бы тоже посмотрел пример с клипами, с visible = false -)
Эммм. Создаю клип с анимацией --> кидаю на сцену --> запускаю --> правой кнопкой выбираю show redraw regions. Вуаля.
разница не чувствуется? Сдается мне, вы при ответе "вырвали" из контекста одну из моих фраз в предыдущих постах :) и не вникли в тему.

Волгоградец
12.11.2009, 15:57
Вы говорите про спрайты, я про клипы.

upd.: проверил. Фактической перерисовки не происходит, о чем говорит стабильный ФПС при добавлении 1000 клипов с visible = false. Вывод: show redraw regions обманывает.

Psycho Tiger
12.11.2009, 16:57
У клипов есть кадры, которые меняются. Он меняет кадр, на этом перерисовка оканчивается.

Тех, кто для удаления использует try, catch - мне не понять. Он работает очень медленно, это раз. И два - какой должна быть структура кода, чтобы везде отлавливать ошибки?

derhab
12.11.2009, 18:44
Эммм. Создаю клип с анимацией --> кидаю на сцену --> запускаю --> правой кнопкой выбираю show redraw regions. Вуаля.
а visible=false клипу присваиваешь?
Вы говорите про спрайты, я про клипы.
я тоже про клипы...неважно что - все то же самое, никаких redraw regions если visible=false

SamFR
13.11.2009, 22:19
почему не лучший способ ? собственно всегд волновал вопрос нормального удаления контейнера перед его пересозданием и выходом нашел, name, собственно работает без ошибок, недостатков кроме задания каждому контейнеру name, нету или я ошибаюсь ?

Мне кажется, getChildByName() должен работать медленнее, чем contains(). Может, я ошибаюсь, но, в любом случае, дополнительное использование имён не придаёт коду ни стройности, ни понятности. А лучшие, по моему мнению, варианты, выглядят так (кстати, выше о них уже упоминали):


//ранее obj, возможно, уже был создан, и (также возможно) добавлен в контейнер
//container здесь указывает на контейнер, в который добавляем объект (если код
//находится в контейнере, то this)
if (obj && container.contains(obj)) container.removeChild(obj);
obj = new Sprite();
container.addChild(obj);


или


//ранее obj, возможно, уже был создан, и (также возможно) добавлен в контейнер
//container здесь указывает на контейнер, в который добавляем объект (если код
//находится в контейнере, то this)
if (obj && obj.parent) obj.parent.removeChild(obj);
obj = new Sprite();
container.addChild(obj);


Ошибок никогда не возникнет ни в первом, ни во втором случаях. Если, конечно, obj имеет тип DisplayObject =)

bicubic_bublic
13.11.2009, 23:07
очень интересно)) а у меня нет
можно пример?

show redraw regions очень хорошо демонстируют, что что-то там происходит (по крайней мере у меня)
может быть, действительно, это не сильно напрягает флешплеер..

вообще show redraw regions довольно странно отображал у меня наследников SimpleButton..

Psycho Tiger
14.11.2009, 19:15
SamFR, всё же код несколько разный. Второй вариант 100% удалит из дисплей листа (хотя я бы parent перекастовал всё же), а в первом никто не гарантирует, что container - это родитель.

SamFR
14.11.2009, 20:13
Ну я и не говорил, что они абсолютно идентичны) Поэтому и привёл тут как первый, так и второй вариант.

А вот зачем перекастовывать parent, понять не могу. Мы же предполагаем, что obj имеет тип DisplayObject, а у него свойство parent имеет тип DisplayObjectContainer, и приведение тут просто незачем. Если же obj может не быть DisplayObject-ом, то мы, скорее всего, где-то ошиблись в проектировании структуры программы. И, в любом случае, простая перекастовка тут не поможет – либо вылетит ошибка (если свойства parent у объекта нет), либо приведение даст null, если свойство имеет несовместимый с DisplayObjectContainer тип. И, опять же, вылетит ошибка, так как мы попытаемся обратиться к методу нуля.

Psycho Tiger
14.11.2009, 23:30
Ох, точно... DisplayObjectContainer. Почему то взбрендело в голову, что просто DisplayObject. Да, SamFR, Вы правы, перекастовывать не нужно.