Jump to content
Search Community

tip: Loading one asset multiple times

Chrysto test
Moderator Tag

Recommended Posts

hi;

 

I did a project where I need to load SWF files of tees and display them. The problem is if you load an asset multiple (for example 3 times) it will occure only to the last (third in our case) when you add it. The solution is very simple - just add cachebuster ( load " assets/main.swf?cb= ' + some random num ' ). This way the flash thinks it load a new object and creates in the memory new pointer for the swf.

 

This works only on web servers :)

Link to comment
Share on other sites

Hey Bassta,

 

Thanks so much for posting your tip. It's a delight to see people helping others out.

 

Just wondering if you know about the noCache property that you can set on any loader:

 

noCache : Boolean - If true, a "gsCacheBusterID" parameter will be appended to the url with a random set of numbers to prevent caching (don't worry, this info is ignored when you LoaderMax.getLoader() or LoaderMax.getContent() by url or when you're running locally)

 

http://www.greensock.com/as/docs/tween/ ... oader.html

 

Happy New Year to you.

 

catch you around.

 

Carl

Link to comment
Share on other sites

Hmmm...I'm a little confused - are you saying that you created 3 different SWFLoaders all with the same URL and it only worked on the 3rd one? That definitely shouldn't be how it works - I'd love to see an example set of files that demonstrate this behavior.

 

You can load the same asset as many times as you want. Each SWFLoader will load it separately. As Carl mentioned, there's no need to add any cache busting random numbers onto your URLs - if you do want to do cache busting, simply set noCache:true on your loader and LoaderMax will automatically do that stuff for you. :)

Link to comment
Share on other sites

Hi;

 

Preloading every time was not an option, it was for project where the SWF Banner was loaded about 5,000 times per second and some of the content is cached. The behaviour was that I have to load 10 t-shirts, if one is missing, it loads default t-shirt. If I load this default t-shirt more than one time, it appears only on the last time I add it. It is the same with LoaderMax and with the default flash loader.

 

The filesize of tha banner couldn't be more than 24k , so I solved this by this way:

 

( when load the XML: )

 

var assetsToLoad:Array = [];			
		var cacheBuster:Number = 0;

		for each(var node:XML in model.getNodeList("r")){
			if(String(node.@url) != ""){ 
				if(assetsToLoad.indexOf(String(node.@url)) == -1){
					assetsToLoad.push(String(node.@url));
				} else {
					cacheBuster++;
					node.@url = node.@url + "?cb=" + cacheBuster;
					assetsToLoad.push(String(node.@url));
				}					
			}

		}

 

I also created my own loader (due to the filesize of the great LoaderMax)

 

package bassta  {

import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.utils.Dictionary;
import flash.system.System;
import bassta.model.Model;
import bassta.model.ModelSettings;

public class ChromeLoader extends EventDispatcher {

	//commit

	private static var _content:Array = [];
	private static var _contentNames:Dictionary = new Dictionary(true);

	private var _loadersCompleted:Number = 0;
	private var _loaders:Array = [];
	private var _loaderNames:Array = [];
	private var _maxTries:Number = 0;
	private var _site:String = "";
	private var _backupUrl:String = "";
	private var _finished:Boolean = false;

	public function ChromeLoader(site:String = null, backupURL:String = null):void {
		if(site){ _site = site }
		if(backupURL){ _backupUrl = backupURL }
	}

	public function loadContents(_items:Array):void{
		for(var i:Number = 0; i< _items.length; i++){
			_loaderNames.push( _items[i] );
		}

		loadContent(_loaderNames[_loadersCompleted]);
	}		

	public function getLoader(_contentID:Number):Loader{
		if(_loaders[_contentID]){
			return _loaders[_contentID];
		} else {
			trace("[ChromeLoader] loader by this ID not found!");
			return null;
		}
	}		

	public function getMovieClip(_clipID:Number):MovieClip{
		if(_loaders[_clipID]){
			return _loaders[_clipID].content as MovieClip
		} else {
			trace("[ChromeLoader] MovieClip by this ID not found!");
			return null;
		}
	}		

	public function clear():void{
		try{
			_content.splice(0, _content.length);				 
			for(var i:Number = 0; i< _loaderNames.length; i++){
				delete( _contentNames[_loaderNames[i]] )
			}				
			for each(var loader:Loader in _loaders){
				loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);	
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onError);	
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.NETWORK_ERROR, onError);
				if (loader.parent) {
					loader.parent.removeChild(loader);
				}
				if (loader.hasOwnProperty("unloadAndStop")) {      //fp10
					loader.unloadAndStop(true); 
				} else {
					loader.unload();
				}					
				loader = null;
			}

		System.gc();

		} catch(error:Error){
			trace("[ChromeLoader error on destroy: ] " + error.message);
		}
	}		

	private function loadContent(_cleanUrl:String):void{			
		_maxTries = 0;
		var contentLoader:Loader = new Loader();
		contentLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);	
		contentLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);	
		contentLoader.contentLoaderInfo.addEventListener(IOErrorEvent.NETWORK_ERROR, onError, false, 0, true);	
		contentLoader.load( new URLRequest( _site + _cleanUrl  ));
		trace("loading: " + String(_loadersCompleted+1) + " out of " + _loaderNames.length + " | " + _site + _cleanUrl);
	}

	private function onComplete(event:Event):void {
		_loaders.push(event.target.content.parent as Loader);			
		_content.push( event.target.content.parent );
		_contentNames[string(_loaderNames[_loadersCompleted])] = event.target.content.parent as Loader;
		_loadersCompleted++;

		if(_loadersCompleted < _loaderNames.length){
			loadContent(_loaderNames[_loadersCompleted]);
		} else {
			_finished = true;
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}

	private function onError(event:Event):void{

		//trace("Alternative teee URL: " + ModelSettings.ALTERNATIVE_TEE_URL);

		_maxTries++;
		if(_maxTries < 3){
			var contentLoader:Loader = new Loader();
			contentLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);	
			contentLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);	
			contentLoader.contentLoaderInfo.addEventListener(IOErrorEvent.NETWORK_ERROR, onError, false, 0, true);	
			contentLoader.load( new URLRequest(ModelSettings.SITE_URL + ModelSettings.ALTERNATIVE_TEE_URL + "?cb=" + Math.ceil(Math.random()*100) ));
			trace("[ERROR] on loading " + _loaderNames[_loadersCompleted] + " .Loading backup file: " + ModelSettings.SITE_URL + ModelSettings.ALTERNATIVE_TEE_URL + "?cb=" + Math.ceil(Math.random()*100));
		} else {
			trace("[ChromeLoader] on Error error - max tries reached! Load never completed!");
		}

		(event.target as LoaderInfo).removeEventListener(Event.COMPLETE, onComplete);	
		(event.target as LoaderInfo).removeEventListener(IOErrorEvent.IO_ERROR, onError);	
		(event.target as LoaderInfo).removeEventListener(IOErrorEvent.NETWORK_ERROR, onError);
	}

	public static function getContent(_contentID:Number):DisplayObject{
		if(_content[_contentID]){
			return _content[_contentID];
		} else {
			trace("[ChromeLoader] Content with this ID( " + _contentID + " )not found!");
			return null;
		}
	}		

	public static function getContentByName(_contentName:String):DisplayObject{
		if(_contentNames[_contentName]){
			return _contentNames[_contentName];
		} else {
			trace("[ChromeLoader] Content with this NAME( " + _contentName + " )not found!");
			return null;
		}
	}

	public function get finished():Boolean{
		return _finished;
	}

}//end
}

 

Feel free to use anyway you like.

 

P.S. --> try to load one image 3 times (w/without LoaderMax) and add it to 3 empty different sprites, see what's gonna happen ;)

Link to comment
Share on other sites

P.S.

 

There's some other code I use... Sometimes I need to load XML, than some assets from it. I know LoaderMax have this capability, but I have no control over the XML node nas, so I had to do my own class.. So here it is;

 

package {

 

import flash.display.Bitmap;

import flash.display.BitmapData;

import flash.events.Event;

import flash.events.EventDispatcher;

 

import com.greensock.loading.LoaderMax;

import com.greensock.loading.ImageLoader;

import com.greensock.loading.XMLLoader;

import com.greensock.loading.SWFLoader;

import com.greensock.events.LoaderEvent;

 

 

public class SiteLoader extends EventDispatcher {

 

//for event dispatching

public static const PROGRESS:String = "ModelLoadingProgress";

public static const ALL_COMPLETE:String = "AllLoadingsCompleted";

public static const XML_COMPLETE:String = "XMLLoadingsCompleted";

 

//singleton

private static var _instance:SiteLoader;

 

private var _loader:LoaderMax;

private var _process:Function;

private var _data:XML;

private var _progress:Number;

 

public function SiteLoader(se:SingletonEnforcer) {

if (_instance != null){

throw new Error("Model singleton already constructed!");

}

_instance = this;

}

 

public static function getInstance():SiteLoader {

if (_instance == null){

_instance = new SiteLoader(new SingletonEnforcer());

}

return _instance;

}

 

public function loadInitialXML(_xmlPath:String, process:Function = null):void{

LoaderMax.activate([xmlLoader, ImageLoader, SWFLoader]);

 

_process = process;

 

var _xmlInitialLoader:XMLLoader = new XMLLoader(_xmlPath, {name:"XMLData", noCache:true})

_xmlInitialLoader.addEventListener(LoaderEvent.PROGRESS, onXMLLoadingProgress);

_xmlInitialLoader.addEventListener(LoaderEvent.COMPLETE, onXMLLoadingComplete);

_xmlInitialLoader.addEventListener(LoaderEvent.ERROR, onError);

_xmlInitialLoader.load();

}

 

//// PRIVATE ////

 

private function onXMLLoadingProgress(event:LoaderEvent):void{

var xmlPercentLoaded:Number = Math.ceil(event.target.progress*100);

if(_process != null){

_progress = xmlPercentLoaded*0.1;

} else {

_progress = xmlPercentLoaded;

}

dispatchEvent(new Event(SiteLoader.PROGRESS));

}

 

private function onXMLLoadingComplete(event:LoaderEvent):void{

_data = new XML( LoaderMax.getContent("XMLData"));

(LoaderMax.getLoader("XMLData") as XMLLoader).dispose(true);

 

dispatchEvent(new Event(SiteLoader.XML_COMPLETE));

 

if(_process != null){

_loader = new LoaderMax();

_loader.addEventListener(LoaderEvent.PROGRESS, onExternallProgress);

_loader.addEventListener(LoaderEvent.ERROR, onError);

_loader.addEventListener(LoaderEvent.COMPLETE, onAllComplete);

_process.call(this);

_loader.load();

} else {

dispatchAllComplete();

}

}

 

private function dispatchAllComplete():void{

dispatchEvent(new Event(SiteLoader.ALL_COMPLETE));

}

 

private function onExternallProgress(event:LoaderEvent):void{

_progress = 10 + (Math.ceil(event.target.progress*100)*0.9)

dispatchEvent(new Event(SiteLoader.PROGRESS));

}

 

private function onError(event:LoaderEvent):void{

trace("[Model]:: ERROR : " + event.text);

}

 

private function onAllComplete(event:LoaderEvent):void{

_loader.removeEventListener(LoaderEvent.PROGRESS, onExternallProgress);

_loader.removeEventListener(LoaderEvent.COMPLETE, onAllComplete);

dispatchAllComplete();

}

 

 

//// PUBLIC - CONTENT ////

 

public function addInternalImageLoader(url:String, parameters:Object = null):void{

_loader.append(new ImageLoader(url, parameters));

}

 

public function getLoaderBitmap(nameOrURL:String):Bitmap{

return (getContent(nameOrURL).rawContent as Bitmap);

}

 

public function getContent(nameOrURL:String):*{

return _loader.getContent(nameOrURL);

}

 

//// PUBLIC - XML ////

 

public function getNodeList(_nodeName):XMLList{

return _data..*.(name() == _nodeName);

}

 

public function getNode(_nodeName):XML{

return _data..*.(name() == _nodeName)[0];

}

 

public function element(nodeName:String, id:String = null, offset:int = 0):XML {

var xml:XML = xmlData..*.(name() == nodeName && attribute("id") == id)[0];

if (offset == 0) {

return xml;

} else {

var offset_xml:* = xml.parent().children()[xml.childIndex() + offset];

return (offset_xml && offset_xml is XML && offset_xml.name() == nodeName) ? offset_xml : null;

}

}

 

//gets the XML

public function get xmlData():XML{

return _data;

}

 

//gets the loaded

public function get loader():LoaderMax {

return _loader;

}

 

//getting the progress

public function get progress():Number{

return _progress;

}

 

}//end class

}

 

internal class SingletonEnforcer { }

 

The ide is to load xml, than execute function (what assets to add). it report 0-100 % progress and much more

 

Use it like var a:SiteLoader = SiteLoader.getInstance();

a.addEventListener( ) //here listeners

 

a.loadInitialXML('path to xm', function():void{

a.addInternalImageLoader( some URL from the a.xmlData --> the loaded XML )

})

 

 

Sorry that it is not documented, but this is VERY handly util for more advanced users.

Link to comment
Share on other sites

P.S. --> try to load one image 3 times (w/without LoaderMax) and add it to 3 empty different sprites, see what's gonna happen ;)

I just tried with LoaderMax. Worked perfectly. No problems whatsoever. All of them showed up individually in their respective containers. What am I missing?

Link to comment
Share on other sites

the reason it appears only one of the 3 instances of the same image is being added to the display list has to do with the way you are creating your loaders and accessing the content.

 

for(var i:uint = 0; i				lm.append( new ImageLoader(image_path);
		}

the problem with that is that you have no unique way of identifying each loader. you have 3 loaders that use the same URL.

 

later on when you do

for(var i:uint = 0; ivar a:DisplayObject = lm.getContent(image_path);

...

}

 

lm.getContent(image_path) is always going to get the content of the first loader that uses image_path as a URL. LoaderMax has no way of knowing that you want the first, second, or third loader that you created with the same image url.

 

If you want to handle each loader and its content in a unique fashion you need to be able to uniquely identify each loader. I suggest giving each ImageLoader a unique name like so:

 

private function loadThumbs(event:Event):void{

		for(var i:uint = 0; i				lm.append( new ImageLoader(image_path, {name:"image" + i});
		}

		lm.addEventListener(LoaderEvent.COMPLETE, addAllImagesToStage);
		lm.load();
	}

	private function addAllImagesToStage(event:LoaderEvent):void{
		var tempX:Number = 0;
		for(var i:uint = 0; i				var a:DisplayObject = lm.getContent("image" + i);

			var transp:Sprite = new Sprite();                                   //just semi-transparent overlay
			transp.graphics.beginFill(Math.random()*0xffffff,0.3);
			transp.graphics.drawRect(0,0,a.width, a.height );
			transp.graphics.endFill();
			transp.addChild(a);

			addChild(transp);
			transp.x = tempX;
			tempX += transp.width + 10;
		}
	}

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...