Strange Flash cache behaviour and attachMovieAnywhere solution
Monday, September 11th, 2006Some days ago I've read about an old problem:
if I load a swf with some identifiers, I can't "attachMovie" them anywhere, but only in the loaded movie:
-
//If you do:
-
myClip.loadMovie("libraryfile.swf");
-
//then you can attach movie only in this scope: "myClip":
-
myClip.attachMovie('clip1', 'foo', myClip.getNextHighestDepth());
-
-
//this doesn't works:
-
_root.attachMovie('clip1', 'foo', _root.getNextHighestDepth());
This can be really a problem if you decide to move some assets to external files too late in the development, probably you'll have to rewrite substantial part of the application or it can be just impossible.
The simplest way to load an external resource and still be able to attach movies everywhere is to "Import for runtime sharing" it, but in this way you can't control via actionscript when to load or change what file to load (for example, to change the theme).
The solution:
Since I've noted some strange behaviour loading files in the flash ide, I've opened my trusty Ethereal sniffer and I've found something interesting:
When flash load a clip and cache it, it will not try to reload it until the page is refreshed.
What does it mean?
-
var mcLoader:MovieClipLoader = new MovieClipLoader();
-
//This send to server: GET /libraryfile.swf HTTP/1.1
-
mcLoader.loadClip("libraryfile.swf", target);
-
-
var mcLoader2:MovieClipLoader = new MovieClipLoader();
-
//This don't send nothing, No bandwidth waste
-
mcLoader2.loadClip("libraryfile.swf", target2);
In the above example, after the first load, every time I'll load "libraryfile.swf" in the movie, flash will take it from the memory and not from the server.
So I can load it everywhere I need it without using any bandwidth. In this way I can attach the loaded resources everywhere in the movie.
The next time the page is loaded, flash will ask the server for the file only the first time.
This can be a problem when we want to check if an swf was modified, in this case we have to put a ? in the filename to be sure the file will be reloaded:
AttachMovieAnywhere:
This simple function can be useful to attach a loaded movieclip anywhere:
-
MovieClip.prototype.attachMovieAnywhere = function(file:String, idName:String, newName:String, depth:Number, initObject:Object ) {
-
if(depth == undefined) depth = getNextHighestDepth();
-
var parent:MovieClip = this;
-
var container:MovieClip = this.createEmptyMovieClip(newName, depth);
-
var mcLoader:MovieClipLoader = new MovieClipLoader();
-
var listener:Object = new Object();
-
listener.onLoadInit = function (mc) {
-
mc.attachMovie(idName, newName, mc.getNextHighestDepth());
-
parent[newName] = parent[newName][newName];
-
}
-
mcLoader.addListener(listener);
-
mcLoader.loadClip(file, container);
-
}
The usage is simple:
-
var container:MovieClip = this.createEmptyMovieClip("container", getNextHighestDepth());
-
container.attachMovieAnywhere('foo.swf', 'clip', 'foo');
-
//One frame later:
-
container.foo._x = 100;
The main difference from attachMovie is that the attached movieclip will not be avaible until the next frame.
Conclusions:
It is a bug? I don't think, this isn't much different form how a browser works: after the first occurrence of <img src="img.jpg"/>, it will not try to reload "img.jpg" if another <img src="img.jpg"/> is found.
So why I haven't found it before? ![]()
Maybe because I have always thought that "loadClip" would have loaded file, maybe receiving a "HTTP1/1 304 Not Modified" reply, instead of silently take the cached one, who knows!
I'm sure there are plenty of experienced flash developers out there that already know this, but I've found many questions about this problem and I hope this can be useful to someone
To be sure that this stuff works I've made a test for it, it was useful to me to better understand how the flash cache mechanism works and to test it on many platform.
Feel free to leave a comment if something doesn't works.
(It is sufficient to view this post to participate, the results will be stored for statistic purpose only)

