V jednom z dokončovaných projektů jsem zjistil zbytečnou zátěž procesoru, která na první pohled neměla žádný rozumný důvod. Profilování ve Flex Builderu také nehlásilo nic neobvyklého a tak musela na řadu přijít klasická metoda reverzního odhalování kritického místa, kterým se nakonec ukázalo použití třídy SharedObject.
Problémem se ukázalo časté dotazování na uložená data, při kterém se v každém novém dotazu vytvářela nová instance třídy SharedObject. Došel jsem k celkem zajímavým výsledkům, kdy například dva dotazy najednou zabraly zhruba 16ms, čtyři už asi 31ms atd. To je pro chod běžných aplikací nepřijatelné. Naštěstí je řešení vcelku jednoduché - nevytvářet pokaždé novou instanci, ale využívat jednu, předem vytvořenou.
Data do SharedObjectu vypadají takto:
var sharedObj:SharedObject = SharedObject.getLocal("myData");
sharedObj.data.nfo = "text";
sharedObj.flush();
A problémový skript pak vypadá následovně:
function getSoData():String{var sObj:SharedObject = SharedObject.getLocal("myData");
var str:String = sObj.data.nfo;
return str;
}function testSharedData(count:uint):void{var dat:Date = newDate();
var ms:Number = dat.getTime();
for(var i:uint=0; i<count; i++){trace(getSoData());
}var dat2:Date = newDate();
var dif:Number = dat2.getTime()-ms;
trace("Čas výpočtu: "+dif+"ms");
}
testSharedData(10);
Po spuštění deseti dotazů na SharedObject třídu se dostaneme k délce trvání zhruba 63ms
Upravená funkce pro získání dat pak využívá předem vytvořenou instanci SharedObject třídy a na výkonu je to citelně znát, uvedený čas je 0ms:
var sharedObj:SharedObject = SharedObject.getLocal("myData");
function getSoData():String{var str:String = sharedObj.data.nfo;
return str;
}
Od společnosti HP máme čerstvě k dispozici užitečný program SWFScan, díky kterému můžeme otestovat SWF soubory a objevit tak případné prohřešky vůči bezpečnostním doporučením pro vývoj flashových aplikací. Varování se nejčastěji týká debug verzí aplikací, které bychom neměli vůbec pouštět do světa, stejně tak odstranění trace funkcí je žádoucí. Aplikace přináší souhrn veškerých odkazů a adres, které se ze SWF souboru dají vyčíst, což nám může také výrazně pomoci. Poslední zajímavou funkcí je možnost exportu ActionScriptu do *.as souboru. Určitě tak tenhle prográmek stojí za vyzkoušení.
Při používání RSL (Runtime Shared Library) ve Flex Builderu jsem po aktualizaci zjistil nekompatibilitu s novou verzí Flex 3.2 SDK:
V nastavení kompileru, respektive u Library Path zůstal odkaz na starou verzi SWF+SWZ knihoven, takže při exportu došlo k chybnému načtení. Jednoduché řešení spočívá v doplnění poslední verze knihoven framework_3.2.0.3958 , které najdeme v balíčku Flex 3.2 SDK
A zase ten Silverlight :) Je ale nutné znát co nejlépe možnosti, výhody a nevýhody konkurenční technologie, takže do toho. Dnes na živě.cz vyšla zprávička o tom, že SL bude možné pouštět i lokálně, bez nutnosti nějakého dodatečného přehrávače (na rozdíl od AIRu). I v článečku na živě.cz se zmiňují, že se jedná o přímou konkurenci k Adobe AIRu. PR informace od MS ohledně jejich nové technologie už beru raději s rezervou, takže jsem se porozhlédnul i jinde: http://blog.digitalbackcountry.com/2009/03/differences-between-silverlight-out-of-browser-experience-and-air/ Těmto zdrojům věřím o poznání více, takže shrnuto podtrženo, přímá konkurence pro AIR to nebude, tím jsou desktopové produkty WPF Spíše bych to viděl jako konkurenci pro flashové aplikace spuštěné v rámci StandAlone FlashPlayeru. Stále totiž vše běží v rámci bezpečnostního prostoru webového prohlížeče, bez možností přístupu na disk, práci se soubory, využití databáze...
Vložení komponenty v žádném případě neznamená, že lze ihned přistoupit k jejím vlastnostem, které plynou z její následné vizualizace a to především velikosti. Příkaz trace v tomto případě vrátí nulovou hodnotu:
var newBtn:Button = newButton();
newBtn.label = "Tlačítko";
container.addChild(newBtn);
trace("šířka: "+newBtn.height);//vrací nulovou hodnotu
Je to z toho důvodu, že vykreslení a aktualizace vlastností komponenty se děje postupně až při nejbližší "příležitosti" - novému renderování scény. Pomocí metody validateNow() lze spustit okamžitou aktualizaci komponenty, takže pak už je možné pracovat s její velikostí:
var newBtn:Button = newButton();
newBtn.label = "Tlačítko";
container.addChild(newBtn);
newBtn.validateNow();
trace("šířka: "+newBtn.height);
//vrátí hodnotu 22//- defaultní u Button komponent
Pokud ovšem potřebujeme pracovat i se změnou velikosti komponenty, do které je například nové tlačítko vloženo, je nutné zavolat metodu validateNow() pronadřazenou komponentu. Obecně je ale vždy vhodnější volat uvedenou metodu vždy z komponenty, která je nadřazená té, u které chceme okamžitě zjistit nové rozměry. Pro nadřazenou komponentu "container" z příkladu by tedy bylo vhodnější použít příkaz:
var newBtn:Button = newButton();
newBtn.label = "Tlačítko";
container.addChild(newBtn);
container.parent.validateNow();
trace("šířka: "+container.height);//vrátí//novou výšku nadřazené komponenty containe
Třída MatrixTransformer je poměrně užitečná, pokud potřebujeme například manipulovat s objekty (měnit velikost, zkosení, rotaci apod.) přes Matrix třídu. Jednou z výborných metod je pak rotateAroundExternalPoint, která nám umožňuje rotaci objektu podle libovolného bodu na scéně. Běžná rotace totiž probíhá přesně podle souřadnicového středu objektu, což může být občas prolém. Následující skript ukazuje využití této metody (po kliknutí se objekt bude otáčet podle nového bodu):
import fl.motion.MatrixTransformer;
var xPoint:int = 200;
var yPoint:int = 200;
var angle:int = 5;
function changeTrasnfPoint(evt:Event):void{
xPoint = this.stage.mouseX;
yPoint = this.stage.mouseY;
}function rotate(evt:Event):void{var matrix:Matrix = obj_mc.transform.matrix;
MatrixTransformer.rotateAroundExternalPoint(matrix,
xPoint,yPoint,angle);
obj_mc.transform.matrix = matrix;
}this.addEventListener( Event.ENTER_FRAME,rotate);
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,
changeTrasnfPoint);
Chvilička zkoušení, abych zjistil, že kulaté rohy pro Canvas a HBox/VBox komponenty nejsou jenom díky stylu cornerRadius, ale že se k tomu musí doplnit i styl pro ohraničení komponenty, tedy borderStyle:
Při práci s XML daty v ActionScriptu 3.0 se moc nezapotíme (vyjma opomenutí data binding, ale o tom jindy). Pokud porovnám práci (spíše trápení) s XMLkem v AS2, tak v AS3 je to doslova hraní.
V případě, že do vstupních XML dat aplikace může zasáhnout lidský faktor, může se stát, že některé hodnoty nedostaneme v požadované formě, jak očekáváme. Klasickým příkladem může být zadávání nepovolených znaků, textu místo čísel a někdy vadí i nesprávné kombinování velkých a malých písmen.
Pokud potřebujeme překontrolovat vstupní data, jednou z možností je odfiltrování konkrétního elementu následujícím způsobem:
var pomList:XMLList = dataXML..xmlElement;
Do XMLList objektu se vloží pouze elementy xmlElement ze zdrojového xml objektu dataXML. Nezáleží, kde jsou umístěné, pomocí dvoutečkové syntaxe získáme zpět opravdu všechny, které se v XML datech vyskytují.
V dalším kroku už stačí projít prvky XMLListu a provést s nimi požadovanou kontrolu. Protože jsou do prvků XMLListu vloženy přímé reference na zdrojové XML elementy, změna se projeví ve zdrojovém XML objektu. Zmíněné zvětšení vstupních dat na velká písmena pak může vypadat takto:
var pomList:XMLList = dataXML..xmlElement; for (var s:uint=0; s<pomList.length(); s++) {
if (String(pomList[s]).length>0) {
pomList[s] = String(pomList[s]).toUpperCase();
}
}
Symboly typu Graphic moc nevyužívám a možná i proto mě poměrně zaujalo zjištění, jak se chovají na scéně. Graphic symbol nemůže mít název instance, proto jej nelze v AS2 ovládat (v AS3 to samozřejmě jde), ale co se stane, když do něj ručně vložíme (ve Flashi CS3/4) nějaký aktivní prvek (tlačítko, MovieClip) a odkážeme se na _parent objekt? Scéna vypadá takto:
Pokud se v MovieClipu objekt_2 odkážeme na nadřazený objekt, dostaneme zpět referenci na objekt_1. Jak to bude vypadat z opačného směru při parsování pomocí AS3?:
var num:uint = objekt_1.numChildren;
trace("num: "+num);
for (var i:uint=0; i<num; i++) {
trace(obj_mc.getChildAt(i));
trace(obj_mc.getChildAt(i).name);
}
Je tak potvrzeno, že pokud vložíme do Graphic symbolu jiný objekt, sice je jakoby uvnitř Graphic symbolu, ale reálně je na stejné úrovni jako samotný symbol Graphics. Je to celkem pochopitelné, protože Shape objekty nemohou obsahovat vložené objekty z DisplayObject třídy. Pouze prostředí Flashe CS3/4 může díky možnosti vkládání objektů do těchto Graphics symbolů přinášet trochu nejasností při jejich zpracování pomocí ActionScriptu.
Při použití List komponenty, u které máme povolen výběr více položek přes atribut allowMultipleSelection="true", nám vrací pole vybraných prvků vždy v tom pořadí, ve kterém provedl uživatel výběr. V některých případech ale potřebujeme získat seznam vybraných prvků přesně v tom pořadí, v jakém jsou umístěn v komponentě, bez ohledu na způsob výběru. Řešením je přistoupení k vybraným objektů pomocí atributu selectedIndices, který vrací indexy vybraných položek (opět v pořadí dle volby uživatele). Před jejich dalším zpracováním stačí už jenom provést seřazení v poli:
var arr:Array = komponentaList.selectedIndices;
trace("Původní pořadí prvků
podle výběru uživatele: "+arr);
arr.sort(Array.NUMERIC|Array.DESCENDING);
trace("Nové pořadí prvků podle
jejich umístění v komponentě: "+arr);
... nezávislý vývojář interaktivních, převážně webových aplikací, založených na Adobe Flash technologii. Vedle této práce rád trávím volný čas rybařením, sportováním, fotografováním, cestováním na vodě i na souši... takže i o tom se zde můžete časem dočíst.
Jsem programátor/vývojář/freelancer interaktivních webových aplikací. V projektech využívám Adobe Flash, Flex Builder, Flash Media Server produkty pro tvorbu RIA aplikací, kterými jsou: interaktivní katalogy obchodů, multimediální prezentace, customizace produktů, 3D aplikace, administrační rozhranní pro informační systémy, vizualizační komponenty, hry, přehrávače videa, streamovaná videa, chaty. Vybrané ukázky naleznete na webu http://www.5d-media.com
Jakmile potřebujeme zjistit pozici uživatele webové aplikace, přijde na řadu IP adresa a hledání její fyzické adresy na zemi. Podívejme se dnes na ukázkový příklad detekce lokace uživatele.
Rychlé vytvoření preloaderu, nebo signalizace stahování externího souboru, to je komponenta ProgressBar, která uvedené funkce umožňuje velmi snadno využívat.