Переменная экземпляра Flash Всегда нулевая?
Я создаю приложение Flex с проблемой, с которой я сталкиваюсь при определении того, была ли переменная инициализирована. Обратите внимание на этот упрощенный пример кода:
<fx:Script>
<![CDATA[
private var pageObject:* = null; //Yes the "*" data type is needed ;)
//Fired by the application elseware
private function constructMenu(e:ResultEvent):void {
if (this.pageObject != null) {
//This block never runs...
// The pageObject will be null when the application
// first runs, so skip this first time around.
// However... this method will be called multiple
// times. Since FoodMenu() is a display object
// and is instantiated below, all subsequent calls
// to this method will require us to remove the old
// display object before adding a new one.
} else {
// This block always runs...
}
setTimeout(function():void {
this.pageObject = new FoodMenu(); //Should now be not-null!!!
//Do more stuff with the FoodMenu() and add to the main application
}, 1000);
}
]]>
</fx:Script>
Исходя из приведенного примера кода и комментариев, может кто-нибудь объяснить, почему this.pageObject
всегда регистрируется как не ноль, независимо от того, сколько раз constructMenu()
метод называется или сколько раз FoodMenu()
класс создан?
Спасибо за ваше время.
Изменить: полный MXML по запросу
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:components="components.*"
xmlns:pagesservice="services.pagesservice.*"
xmlns:menuservice="services.menuservice.*"
minWidth="955" minHeight="600" backgroundColor="0x141414"
creationComplete="init(event)" skinClass="skins.Theme" xmlns:pages="components.pages.*" xmlns:reviewsservice="services.reviewsservice.*">
<fx:Script>
<![CDATA[
import com.asual.swfaddress.*;
import com.forwardfour.boncuisson.events.MenuEvent;
import com.greensock.TweenMax;
import com.greensock.plugins.VisiblePlugin;
import components.header.Menu;
import components.pages.FoodMenu;
import flash.utils.setTimeout;
import mx.controls.Alert;
import mx.core.IVisualElement;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import skins.Theme;
import spark.components.Group;
//Globalize a reference to the navigation menu
private var menu:Menu;
//Globalize a reference to the page content
private var pageObject:* = null; //This reference will be various types, so just make a general object
/**
* Initialization
* -------------------------------
*/
//Add an event listener for when "links" on the menu are clicked and initialize SWFAddress
private function init(event:FlexEvent):void {
//Listen for menu clicks
var skin:Theme = Theme(this.skin);
this.menu = Menu(skin.menu);
this.menu.addEventListener(Menu.MENU_ITEM_CLICKED, menuNavigateToPageHandler);
//Initialize SWFAddress
SWFAddress.addEventListener(SWFAddressEvent.INIT, initSWFAddress);
}
//Initialize SWFAddress and grab the page listed from the URL
private function initSWFAddress(e:SWFAddressEvent):void {
//Listen for change events
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, URLNavigateToPageHandler);
//Fetch the page from the URL
var URL:String = SWFAddress.getValue();
if (URL == "" || URL == "/") {
pagesResponder.token = page.getPagesByPosition(1);
} else {
pagesResponder.token = page.getPagesByURL(URL.substring(1));
}
}
/**
* Navigation handlers
* -------------------------------
*/
//Go to a specific page when a menu item has been clicked
private function menuNavigateToPageHandler(e:MenuEvent):void {
SWFAddress.setValue(e.pageURL);
pagesResponder.token = page.getPagesByID(e.pageID);
}
//Request a page when the URL has changed
private function URLNavigateToPageHandler(e:SWFAddressEvent):void {
var URL:String = SWFAddress.getValue();
if (URL == "" || URL == "/") {
pagesResponder.token = page.getPagesByPosition(1);
} else {
pagesResponder.token = page.getPagesByURL(URL.substring(1));
}
}
/**
* Loading content
* -------------------------------
*/
//Show an error dialog in the case of an error when communicating with the server
private function requestErrorHandler(e:FaultEvent):void {
Alert.show("Fault string: " + e.fault.faultString + "\nFault detail: " + e.fault.faultDetail, e.fault.faultCode);
}
//Determine what kind of page will be constructed
private function determinePage(e:ResultEvent):void {
var pageType:String = pagesResponder.lastResult.type;
//We will need to know the type of page to build
switch(pageType) {
case "menu" :
menuResponder.token = menuFetch.getMenuByType(pagesResponder.lastResult.category);
break;
case "lunch" :
break;
case "reviews" :
reviewsResponder.token = reviews.getAllReviews();
break;
case "home" :
default :
break;
}
}
//Using the data that was fetched from the "menuFetch" service, construct the page of type menu
private function constructMenu(e:ResultEvent):void {
//Transition the existing page out of view
if (this.pageObject != null) {
Alert.show("i");
TweenMax.to(this.pageObject, 0.75, {
alpha : 0,
y : 20
});
removeElement(this.pageObject);
}
setTimeout(function():void {
this.pageObject = new FoodMenu();
this.pageObject.alpha = 0;
this.pageObject.y = 20;
this.pageObject.data = menuResponder.lastResult;
addElement(this.pageObject);
//Tween the new menu into place
TweenMax.to(this.pageObject, 0.75, {
alpha : 1,
y : 0
});
}, 1000);
}
]]>
</fx:Script>
<!-- Make a request to the server for the page data -->
<fx:Declarations>
<pagesservice:PagesService id="page"/>
<s:CallResponder id="pagesResponder" fault="requestErrorHandler(event)" result="determinePage(event)"/>
<menuservice:MenuService id="menuFetch"/>
<s:CallResponder id="menuResponder" fault="requestErrorHandler(event)" result="constructMenu(event)"/>
<reviewsservice:ReviewsService id="reviews"/>
<s:CallResponder id="reviewsResponder" fault="requestErrorHandler(event)" result="constructMenu(event)"/>
</fx:Declarations>
</s:Application>
1 ответ
Решение
Одна из возможных проблем, с которыми я сталкиваюсь, связана с этим фрагментом кода:
setTimeout(function():void {
this.pageObject = new FoodMenu(); //Should now be not-null!!!
//Do more stuff with the FoodMenu() and add to the main application
}, 1000);
Указатель this указывает на что-то другое (возможно, глобальный объект) в замыкании.
Попробуйте следующее, чтобы убедиться в этом:
trace(this);
setTimeout(function():void {
trace(this);
},1000);