Friday, 3 September 2010

Air Swf loading anomolies

The application I do most of my work on (An AIR 1.5 app) loads swfs in 2 ways.

There are modules of functionality that are loaded into the application sandbox using the secure loading method that I've blogged about here before.

There are also 'lessons' which consist of multiple swfs that are loaded into the non-application sandbox. If a lesson consists of 4 swfs then they are all loaded, and then they are added to / removed from the stage as the user browses through the lesson. When another lesson is loaded the previous lesson swfs are first unloaded.

These swfs are having code injected into their timelines, but they also contain code at timeline depth and in nested MovieClips. This is generally just simple 'show this label on MouseOver' functionality. Nothing fancy.

I found a few months ago that loading the swfs serial - as you would expect to do [by waiting for one to INIT before loading the next] - caused the code in the nested MovieClips to *often* fail - on Mac or PC. I tried to track down the cause of this, and through my experiments I discovered that loading the swfs parallel seemed to solve the problem. So, unable to discover a reason I went with the approach that worked.

Now the problem has reared its ugly head again - but only on PC. On Mac, all code works fine all the time.

On PC (Windows XP), the timeline code, and the injected code, are always fine. But MovieClip code - whether done in a separate class file or just put into the MC timeline, is borked in SOME swfs, depending on what order the swfs INIT in.

So far I've discovered the following:

1) Loading the swfs serial, MC code is frequently borked on Mac or PC.

2) Loading the swfs parallel, code borking is dependent on the INIT order. [Might this indicate that the swf isn't fully loading when it INITs first?]

3) Whether the code is directly in the MC, or just in the MC timeline, it's just not there - even a stop() doesn't work.

4) I've replicated the problem with simple assets (a 2 frame MC with diff coloured squares and a stop() on frame 1), guaranteed not to clash with any other assets in any other swf being loaded.

5) The swfs most likely to be borked are those with the largest file size. BUT removing some assets to reduce the file size doesn't appear to help.

6) The swfs are currently being exported from Flash Pro CS4. I'm downloading CS5 trial just incase it helps. They're FP10.

7) Some swfs are only borked if they INIT first. Some are able to tolerate being the first to INIT without problems. Some are borked if they're first OR second (of six in that case) to load.

8) Adding a pause after all the swfs have loaded, before I do anything else, makes no difference.

9) Air runtime is 2.0.3

--- EDIT - conclusion

I think I've found the source of the problem.

The load order and the broken movieclip code are both symptoms of the same problem: the swf has not loaded into memory correctly.

The broken swfs are usually the largest, and when they INIT ahead of much smaller swfs it's probably a sign of incomplete loading, hence the correlation with Level-1 code not running. (Level-0 is timeline, level-1 is code inside MCs on that timeline etc).

Having run the tests hundreds of times I've found that this problem occurs approximately 50% of the time in a Parallels-XP virtual PC, and occasionally on a Windows 7 machine that has been down-versioned to windows XP (and hiccups in many other areas). So far it does not happen on a Mac book pro bootcamp XP install, or a stable Vista install.

I guess it's a genuine thread crash in the Air app, most likely some sort of memory issue?

I have not been able to find a way to prevent the problem from happening. Instead I have a work around:

Each swf contains a MC on the timeline on frame 1 with a line of code with the sole purpose of notifying the application (via the sandbox bridge) that level-1 code has been loaded correctly. If this notification is not received for a particular swf by the time the 'COMPLETE' event fires, the swf is deemed to have loaded incorrectly, and is unloaded from memory and loaded again.

This process is repeated until the load is correct. The files are local so the delay to the user is minimal.

No comments: