Jump to content
GreenSock

tiagoalencar

unload() x load() again

Recommended Posts

Hi everybody,

 

I've wasted the last hours trying to figure out this situation:

 

I'm building a video galery which has the main video and some thumbs of other videos.

 

1. I load a SWF file (main video);

2. I unload this SWF (when user clicks a thumb);

3. I need to load another video on the same container... this is the problem...

 

look my code:

 

var carregaVideos:LoaderMax = new LoaderMax({name:"mainQueue",onProgress:progressYoutube,onComplete:completeYoutube,onError:errorYoutube,onChildComplete:childYoutube});

 

var youtube:SWFLoader = new SWFLoader("blablabla", {name:"videoPrincipal", container:principal.alvo});

 

carregaVideos.append( youtube );

carregaVideos.load();

 

Then, when the user clicks any thumb I unload the main video:

 

youtube.unload();

 

And try to load another one:

 

var youtube:SWFLoader = new SWFLoader(blablabla", {name:"video"+obj.name.substr(7,1), container:principal.alvo, onProgress:progressYoutube, onComplete:videoYoutube});

carregaVideos.append( youtube );

carregaVideos.load(true);

 

then I get this error message:

 

Error #1009: Cannot access a property or method of a null object reference

 

Does anyone know what i'm doing wrong?

 

Thanx in advance,

 

Tiago

Link to comment
Share on other sites

You've obviously got a null reference somewhere but it's very difficult to know where without seeing your file and testing some things. You can try commenting out chunks of code until the error goes away and then it gives you a clue as to where the null object reference is. Use trace() a lot.

 

Also, I noticed you're using a LoaderMax queue but only putting one loader into it. That's fine, but you don't need to wrap all your loaders in a LoaderMax. It's perfectly acceptable to use a SWFLoader on its own. You can add onComplete, onProgress, and many other events directly on the SWFLoader and load() it, etc.

 

If you want to fully dispose of a SWFLoader and all its content, use dispose(true) instead of unload(). If you only unload() a SWFLoader, the swf that it loaded will be unloaded but the loader instance itself will remain. So in your case, it would still be in the parent LoaderMax and then when you load() the LoaderMax, it'll reload that swf into the SWFLoader.

Link to comment
Share on other sites

Hi there,

 

Thanx for the quick answer...

 

I'm using the LoaderMax queue because there are more stuff being loaded... : )

 

The problem occurs when I click any thumbnail to load another video...

 

I want load a video to replace the main one.

 

I have 8 thumbnails, every time I click one I need to load a different video in the same place...

 

Here's the code of the release function:

function releaseYoutube(evt:MouseEvent):void
{
var obj:Object = new Object();
obj = evt.target;

trace (obj.name.substr(7,1));

youtube.unload();
TweenMax.to(principal.carregador, .5, {autoAlpha:1});	

     //UNTIL HERE THE CODE IS EXECUTED...


    //HERE STARTS MY PROBLEM...
var youtube:SWFLoader = new SWFLoader(MovieClip(root).youtubeLista[obj.name.substr(7,1)].media::group.media::content.(String(@url).substr(0,4) == "http").@url+"&rel=0", {name:"video"+obj.name.substr(7,1), container:principal.alvo,onProgress:progressYoutube,onComplete:videoYoutube});
carregaVideos.append( youtube );
carregaVideos.load(true);
}

 

I think it's simple to resolve.... but I can't figure out.

 

Is there a way to unload a SWFLoader and the use this same instance do load a different SWF?

 

Thanx again,

 

Tiago.

 

I'll paste the entire code here:

stop();

import com.greensock.*;
import com.greensock.loading.*;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.display.*;

var media:Namespace = MovieClip(root).youtubeXML.namespace("media");
var yt:Namespace = MovieClip(root).youtubeXML.namespace("yt");

principal.alvo.visible = false;

var carregaVideos:LoaderMax = new LoaderMax({name:"mainQueue",onProgress:progressYoutube,onComplete:completeYoutube,onError:errorYoutube,onChildComplete:childYoutube});
var youtube:SWFLoader = new SWFLoader(MovieClip(root).youtubeLista[a].media::group.media::content.(String(@url).substr(0,4) == "http").@url+"&rel=0", {name:"videoPrincipal", container:principal.alvo});

for (var a:int = 0; a<8; a++)
{
this["youtube" + a].alvo.alpha = 0;
this["youtube" + a].addEventListener(MouseEvent.CLICK, releaseYoutube);
this["youtube" + a].addEventListener(MouseEvent.ROLL_OVER, rollOverYoutube);
this["youtube" + a].addEventListener(MouseEvent.ROLL_OUT, rollOutYoutube);
this["youtube" + a].buttonMode = true;
this["youtube" + a].mouseChildren = false;

if (a == 0)
{
	carregaVideos.append( youtube );
	carregaVideos.append( new ImageLoader(MovieClip(root).youtubeLista[a].media::group.media::thumbnail[0].@url, {name:"thumb"+a, width:88, height: 65.5, container:this["youtube"+a].alvo}) );
}
else
{
	carregaVideos.append( new ImageLoader(MovieClip(root).youtubeLista[a].media::group.media::thumbnail[0].@url, {name:"thumb"+a, width:88, height: 65.5, container:this["youtube"+a].alvo}) );

}

}

carregaVideos.load(true);

function childYoutube(event:LoaderEvent):void
{
if (event.target.name == "videoPrincipal")
{
	principal.alvo.scaleX = principal.alvo.scaleY = .8;
	TweenMax.to(principal.carregador, .5, {autoAlpha:0});
	TweenLite.to(principal.alvo, 2, {autoAlpha:1});
	trace ("video");

}
else
{
	TweenMax.to(this["youtube"+event.target.name.substr(5,1)].carregador, .5, {autoAlpha:0});
	TweenMax.to(this["youtube"+event.target.name.substr(5,1)].alvo, .5, {alpha:1, delay:.5});
	trace("thumbs");
}


}


function progressYoutube(event:LoaderEvent):void
{
trace("progress: " + event.target.progress);
}

function completeYoutube(event:LoaderEvent):void
{

trace(event.target + " is complete!");

}

function errorYoutube(event:LoaderEvent):void
{
trace("error occured with " + event.target + ": " + event.text);
}

function rollOverYoutube(evt:MouseEvent):void
{
var obj:Object = new Object();
obj = evt.target;

TweenMax.to(obj, .5, {alpha:.5});
}

function rollOutYoutube(evt:MouseEvent):void
{
var obj:Object = new Object();
obj = evt.target;

TweenMax.to(obj, .5, {alpha:1});
}

function releaseYoutube(evt:MouseEvent):void
{
var obj:Object = new Object();
obj = evt.target;

trace (obj.name.substr(7,1));

youtube.unload();
//youtubeGaleria.unload();
TweenMax.to(principal.carregador, .5, {autoAlpha:1});

//trace (principal.alvo)

var youtube:SWFLoader = new SWFLoader(MovieClip(root).youtubeLista[obj.name.substr(7,1)].media::group.media::content.(String(@url).substr(0,4) == "http").@url+"&rel=0", {name:"video"+obj.name.substr(7,1), container:principal.alvo,onProgress:progressYoutube,onComplete:videoYoutube});
carregaVideos.append( youtube );
carregaVideos.load(true);
}

function videoYoutube(event:LoaderEvent):void
{
	TweenMax.to(principal.carregador, .5, {autoAlpha:0});
	TweenLite.to(principal.alvo, 2, {autoAlpha:1});
}

Link to comment
Share on other sites

Ps.: Even when I try to reload the same SWF in a instace that I unload before I've got that message: Error #1009: Cannot access a property or method of a null object reference...

 

Tiago

Link to comment
Share on other sites

You're using a local variable inside a function and then trying to reference that again inside the function the next time it runs. You cannot do that.

 

BAD:

function badFunction():void {
   myVariable.unload(); //myVariable doesn't exist! 
   var myVariable:SWFLoader = new SWFLoader(...); //now myVariable exists
   //as soon as badFunction() finishes running, the myVariable variable reference is deleted!
}

 

GOOD:

var myVariable:SWFLoader; //notice I define it OUTSIDE the function so it persists.
function goodFunction():void {
   if (myVariable != null) {
       //the first time the function runs, myVariable is null so skip trying to unload()
       myVariable.unload();
   }
   myVariable = new SWFLoader(...);
}

 

Also, I would recommend NOT reusing the same loader. Instead, what I typically do is create a new SWFLoader each time I need to load a swf so that I can fade its content in over the top of the other one (they both need to coexist for that to happen) and then use an onComplete on my fade out tween on the old/stale one to call dispose(true) on it when the new one has taken the place of the old one (faded in). Technically you can use the same loader by simply setting its "url" property to a new value and calling load() again, but I just don't think it's typically the best option.

Link to comment
Share on other sites

  • 2 weeks later...

Jack,

 

Something else may be going on here. I've encounter what may be the exact same problem... but only with more recent versions of the LoaderMax class.

 

Here is my example:

function loadPhotos(e:Event=null):void {
for (var i=0; i		//trace("    Queing: "+xmlData.photo[i])
	photos[i]=new Sprite;
	queue.append( new ImageLoader(xmlData.photo[i], {name:i, container:photos[i], onComplete: countLoaded, onIOError:errorLoading, maxConnections:4, blendMode:"lighten" }) );
}
//start loading
queue.load();

intervalTimer = new Timer(interval);
intervalTimer.addEventListener(TimerEvent.TIMER, nextImage, false, 0, true );		
intervalTimer.start();
}

function nextImage(e:TimerEvent):void {
   // Images get added to the stage in sequence, several visible at a time.
   // When the display time of each is ended removePhoto() is called to free up RAM
}

function removePhoto():void {
if (remvPic > -1) {
	var Name:String = String(remvPic);    
                   // Note: Makes no difference if "Name" is declared here or outside the function.
	removeChild(photos[remvPic]);

	// needed to keep RAM usage low
	LoaderMax.getLoader(Name).unload();  // <<<< crashes here  <<<<
	LoaderMax.getLoader(Name).load();
}
remvPic = prevPic;
prevPic = currPic;
currPic = nextPic;
nextPic ++;
if (nextPic > (numPhotos - 1)) {
	nextPic = 0;
}
}

With the LoaderMax class I downloaded on 7/15 this runs fine. With the version I downloaded on 8/14 it crashes. Same with the version I downloaded today, 9/17.

 

It seems that between 7/15 and 8/14 you changed some code that affects how the unload() method functions.

 

BTW, you may remember my fireworks project from July. The reason I unload then reload the same image is that if I don't RAM usage climbs by more than a Gig. By unloading each image when its display is over RAM usage stays nice and low. The reload makes the image available the next time it is needed in the display loop.

Link to comment
Share on other sites

Hmm, it sounds like there might be something else going on in your code. I just tested ImageLoader to see if I could make the player crash by calling unload() and then load() on the same loader every 2 seconds continually and I couldn't make it crash. Worked great.

 

I'm not sure what's going on with your interval (how long it is, where you stop it from continuing, etc.)

 

This is one of the reasons I almost always ask for a sample FLA that demonstrates the issue - it allows me to just publish your particular file and see exactly what's going on. I can add trace() statements, etc. to help diagnose. But as it is I cannot seem to reproduce the problem so I'm stabbing in the dark. Remember when you sent me your fireworks files and I was able to very quickly identify the issue and get back to you with a solution? Could you post a sample here (or e-mail it to me)?

Link to comment
Share on other sites

Jack,

 

Don't you have a magic wand or something you can just wave? :?

 

I didn't have time to assemble what was needed yesterday but just sent a PM with everything to reproduce the problem with comparison between the old and current class versions. Looking forward to hearing what you find out. And thanks so much for the very quick and effective customer service. Seriously, you are the best.

Link to comment
Share on other sites

Ah, yet another Flash bug. The problem stemmed from the fact that if you set the loader's name to simply the Number 0, Flash will report true for this condition: Boolean(vars.name == ""). Yep, that's right, it thinks the number 0 is the same as the String ""! I had to cast it as a String to make it work, like Boolean(String(vars.name) == ""). That's fixed in the latest version. http://www.LoaderMax.com

 

So in your code, you were using numbers as the names of all your loaders. For the one with the name "0", LoaderMax.getLoader(0) was returning null and that's why you got the error. Had you named it anything besides the Number 0, it would have worked fine. You said it crashed Flash, but I assume you meant that it just threw an error. In any case, it should be fixed with the latest update.

Link to comment
Share on other sites

Doesn't it feel good to solve at least one impossible puzzle per day?? :D That was a weird one.

 

Had you named it anything besides the Number 0, it would have worked fine. You said it crashed Flash, but I assume you meant that it just threw an error.

Or had I set the numbers to strings in the first place and used those as the names I gather it would have worked fine. I am curious that it works with the older version of LoaderMax, however.

 

And yes, it didn't crash Flash. My bad. It threw errors which stopped Flash if you run the debug version.

 

BIG thanks for making the code change.

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.
×