PDA

Просмотр полной версии : Загрузка XML etc


Ruffus
11.06.2008, 00:36
Была проблема в теме "Две абсолютно непонятных фигни".
Я выяснил, что происходит такая штука. Если переменная dataNode является переменной класса, то после загрузки в неё XML в методе этого класса loaded, status, да и сама переменная принимают значения undefined.
Можно обойти это дело если воспользоваться локальной переменной:

private function loadFromFile(fileName: String) {
var node: XML = new XML();
node.ignoreWhite = true;
node.onLoad = function(success) {
dataNode = node; //не знаю стоит ли писать тут dataNode = node.cloneNode(true);
trace('one..');
loadDatas();
trace('thre..');
notifier.dispatchEvent("dataLoaded", _parent);
}
}
private function loadDatas() {
trace('two..');
.......
}

Данные из XML теперь грузятся, но появляется новая проблема. Внутри обработчика onLoad this указывает уже не на экземпляр базового класса, а на node. Поэтому вызов функции loadDatas() сваливается и на экране видно:

one
three

Как бы обойти эту вещь?

iNils
11.06.2008, 00:59
1. Создавать функцию внутри метода не правильно.
2. Пользуйтесь классом mx.utils.Delegate для смены областей видимости внутри событий.
Должно получиться примерно так:
import mx.utils.Delegate;
...
class ...
private function loadFromFile(fileName: String) {
var node: XML = new XML();
node.ignoreWhite = true;
node.onLoad = Delegate.create (this, loadDatas);
}
private function loadDatas() {dataNode = node;
//не знаю стоит ли писать тут dataNode = node.cloneNode(true);
trace('one..');
trace('two..');
.......
trace('thre..');
notifier.dispatchEvent("dataLoaded", _parent);
}

Ruffus
11.06.2008, 09:38
Спасибо, попробую

Ruffus
11.06.2008, 11:35
Ньюанс: переменная node не видна из метода-делегата.
И ещё вопрос. Чем отличается использование этого Delegate от записи типа

node.onLoad = onDataLoad;

private function onDataLoad(success:Boolean) {
loadDatas();
...
}

iNils
11.06.2008, 13:20
переменная node не видна из метода-делегата.
Вынести
var node: XML = new XML();
за пределы метода. Внутри метода описывайте только временные переменные. И не называйте ее node, назовите xml. Имя node должно быть у объектов класса XMLNode, а так вы и себя и других запутаете.
Чем отличается использование этого Delegate от записи типа node.onLoad = onDataLoad;
В такой записи this будет указывать на XML, и достучаться до самого объекта, который загрузил XML вы не сможите. Поэтому нужно сохранить область видимости неизменной, что и делает Delegate. Тогда внутри onDataLoad, this будет ссылаться на экземпляр класса, а доступ к XML будет осуществляться через node.

Ruffus
11.06.2008, 21:17
Я могу вынести node за пределы метода, сделав его переменной класса. ТОгда я вернусь к ситуации, в которой после вызова load происходит не пойми что, свойства loaded и status становятся undefined. Об этом я писал в предыдущей теме.
------------
Хотя щас вот с делагатом вроде адекватно стало всё.
Спасибо ещё раз.
------------
Щас пишу код

_notifier = new EventDispatcher();
_notifier.addEventListener("dataLoaded", _parent);

private function onDataLoad(success:Boolean) {
loadDatas();
trace('333');
_notifier.dispatchEvent("dataLoaded");
trace('555');
}

В родительском классе

public function dataLoaded(event: String) {
trace("dispatched!");
prepare();
_needProcessing = true;
paint();
}

Не трассирует dispatch почему-то.

Написал так

_notifier = new EventDispatcher();
_notifier.addEventListener("loaded", _parent);

private function onDataLoad(success:Boolean) {
loadDatas();
trace('333');
_notifier.dispatchEvent({target: this, type: loaded});
trace('555');
}

Диспатч проходит теперь, но в методе dataLoaded класса Viewer опять проблема с видимостью. Там окружением считается экземпляр EventDispatcher. Опять что-то с делегатом надо сочинять?
Пробую. Но говорит, но делегируемая функция теперь в другом классе (раньше она была в Hall, теперь во Viewer), и компилятор ругается на неё.
------------
Я подумал в итоге, что все эти диспатчи. Без них можно. Они только мешают тем, что путают области видимости. А если _parent.dataNode у меня единственный слушатель события, то наверное проще его сразу и вызывать из метода дочернего класса.
Я прав?)

wvxvw
11.06.2008, 22:29
нет... вы сами себя путаете... все гораздо проще.

import mx.utils.Delegate;

class XMLLoader extends XML {

public function XMLLoader(s:String)
{
super(s);
ignoreWhite = true;
onLoad = onLoadDelegate;
//onLoad = Delegate.create (this, onLoadDelegate);
//будет работать одинаково, область видимости та же
}

public function onLoadDelegate(b:Boolean):Void
{
if (b) {
trace(toString());
} else {
trace('error!');
}
}
}
import XMLLoader;
import mx.utils.Delegate;

var xl:XMLLoader = new XMLLoader();
xl.onLoad = Delegate.create(this, overrideDefaultOnLoad);
// изменит область видимости
xl.load('foo.xml');
var foo:String = 'bar';
function overrideDefaultOnLoad(b:Boolean):Void
{
trace(foo);
trace(xl);
}

Ruffus
12.06.2008, 03:25
Не понимаю, что это должно мне доказать.
Тем более, что у меня по сути метод overrideDefaultOnLoad находится в другом классе, поэтому не виден в данной конструкции.

wvxvw
12.06.2008, 03:31
Тем более, что у меня по сути метод overrideDefaultOnLoad
А вы не видите сходства с вашей ситуацией? =) Тут тоже метод другого бъекта вызывается.
this в XMLLoader и вo втором примере - это разные объекты - именно та ситуация, которую вы описали. Именно для этого и придуман Delegate.

Т.е. как бы вы ни придумывали хитрые схемы по загрузке ХМЛ (я думаю, что если порыться на форуме - их с сотню, наверное, можно будет набрать =)
Вам все равно прийдеться прийти к ситуации когда:

а. Загружаемый ХМЛ виден из объекта, у которого вы пытаетесь вызвать метод обрабатывающий ХМЛ (фз, звучит, как масло масляное, но, факт, именно так и должно быть =). *метод не обязан быть "родным", можно использовать функцию объявленную в совсем другом месте, но вызвать ее все равно нужно будет именно там, где виден ХМЛ.*

либо

б. передать ХМЛ методу (тогда уже область видимости не важна).

Ruffus
12.06.2008, 14:20
а. Загружаемый ХМЛ виден из объекта, у которого вы пытаетесь вызвать метод обрабатывающий ХМЛ (фз, звучит, как масло масляное, но, факт, именно так и должно быть =). *метод не обязан быть "родным", можно использовать функцию объявленную в совсем другом месте, но вызвать ее все равно нужно будет именно там, где виден ХМЛ.*

Это понятно. Спасибо. Сейчас ньюанс в том, что мне надо сделать так
Delegate.create (_parent, onLoadDelegate);
Это нужно для вызова обработчика сообщений, потому что обрабатывающий метод по логике находится в родительском классе. Но текущий класс не знает о функции onLoadDelegate. Поэтому я решил, что проще вызывать эту функцию напрямую, без заморочек с EventDispatcher и проч.

wvxvw
12.06.2008, 14:57
Delegate.create (_parent, _parent.onLoadDelegate);