Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   Загрузка XML etc (http://www.flasher.ru/forum/showthread.php?t=112889)

Ruffus 11.06.2008 00:36

Загрузка XML etc
 
Была проблема в теме "Две абсолютно непонятных фигни".
Я выяснил, что происходит такая штука. Если переменная 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 и проч.


Часовой пояс GMT +4, время: 00:26.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.