Weird order of events!?!

Hi,

I’m using the storyboard API and in my main I have a system event listener that loads my apps data, here a cut down version of the main.lua

[lua]

local function onSystemEvent( event ) 

   print ("OnSystemEvent – event name = " … event.name … ", event type = " … event.type … " – Previous event type: " … tostring(previousEvent))

   if  “applicationExit” == event.type then

      print(“exiting!!!”) 

      saveTable(storyboard.state.data, “data.json”)

   elseif “applicationOpen” == event.type then

      native.showAlert( “Open via custom url”, event.url, { “OK” } )

   elseif “applicationStart” == event.type then

      print(“loading data…”)

      storyboard.state.data = loadTable(“data.json”)

      – if there’s no file best build the table structure!

      

      print(storyboard.state.data[1])

      if (storyboard.state.data == nil) then

         print(“no data found”)

         storyboard.state.data = {}

         

      end

   else

      – For all other events, check to see if file exist

   end

   

   

   return true

    

end

– Add the System callback event

Runtime:addEventListener( “system”, onSystemEvent );

print(storyboard.state.data[1])

– load first scene

storyboard.gotoScene( “listGuitar”, “fade”, 1 )

[/lua]

In my listGuitar.lua I have in the createScene a print line at the top  

print("-- listGuitar : createScene")

However when I run the output is:

nil    

– listGuitar : createScene    

nil    

OnSystemEvent – event name = system, event type = applicationStart – Previous event type: nil    

loading data…    

table: 0x10c007950    

So the createScene in the listGuitar.lua is happening before the system event applicationStart!!!

Why is that I wondered then I read in the docs

“You app will receive an “applicationStart” event when your app launches (from a closed/cold state, not a suspended state), and after the code in main.lua has executed.”

I want to load my data in the main at the application start THEN in the first scene build a table view with the contents of the data read in BUT the scene seems to be created BEFORE the application start event.

So I removed the loading of the data from the listener and put it outside of it but prior to the scene change like this

[lua]

Runtime:addEventListener( “system”, onSystemEvent );

storyboard.state.data = loadTable(“data.json”)

if (storyboard.state.data == nil) then

      storyboard.state.data = {}

end

– load first scene

storyboard.gotoScene( “listGuitar”, “fade”, 1 )

[/lua]

now it works.   Hope my fumblings help someone else caught out by this!

I’ve got a more detailed sequence of events that might help you to understand the fumblings better, and perhaps adjust your code differently or deal with similar issues that could crop up in other parts of your code.

Probably the most important thing is that the call to Runtime:addEventListener( “system”, onSystemEvent ) only queues up the system listener to be added *later*, after the current module has finished being processed (end of file for main.lua in this case). This means the runtime event “system” will *not* be called until all the code in (presumably) main.lua has finished being processed.

So the system event is not sent in your first example until *after* line 37 in your original program has processed. A lot of corona event handlers work this way - for example, if you change an objects x,y coords in an event handler, no change happens onscreen until after the handler exits (you can test this by making an infinite loop in an event handler after making a visual change to the display, and then running the app to see if it changed onscreen without ever exiting the event handler – it doesn’t).

The most common method I’ve seen to get around this is the old timer.performWithDelay() call. In your case, adding this to your original program would probably resolve the issue as well. Changing the end of your program to this would probably work:

[lua]

local function doStory()

   print(storyboard.state.data[1])

   – load first scene

   storyboard.gotoScene( “listGuitar”, “fade”, 1 )

end

timer.performWithDelay( 500, doStory )

[/lua]

The 500 millisecond delay is enough time for the lua interpreter to finish processing to the end of main, and then install the handler, and then to even call it as well.

Another way to put is that this allows the system event handler to fully install, and then (after 500 milliseconds), call the storyboard display stuff.

With this change, the sequence should be:

  • Main executes.

  • Immediately when main finishes executing, system event handler is installed

  • System event handler is called with “startup” event

  • 500 ms passes and doStory() gets called

Nice one, thank you!

Why is that I wondered then I read in the docs

“You app will receive an “applicationStart” event when your app launches (from a closed/cold state, not a suspended state), and after the code in main.lua has executed.”

I want to load my data in the main at the application start THEN in the first scene build a table view with the contents of the data read in BUT the scene seems to be created BEFORE the application start event.

So I removed the loading of the data from the listener and put it outside of it but prior to the scene change like this

[lua]

Runtime:addEventListener( “system”, onSystemEvent );

storyboard.state.data = loadTable(“data.json”)

if (storyboard.state.data == nil) then

      storyboard.state.data = {}

end

– load first scene

storyboard.gotoScene( “listGuitar”, “fade”, 1 )

[/lua]

now it works.   Hope my fumblings help someone else caught out by this!

I’ve got a more detailed sequence of events that might help you to understand the fumblings better, and perhaps adjust your code differently or deal with similar issues that could crop up in other parts of your code.

Probably the most important thing is that the call to Runtime:addEventListener( “system”, onSystemEvent ) only queues up the system listener to be added *later*, after the current module has finished being processed (end of file for main.lua in this case). This means the runtime event “system” will *not* be called until all the code in (presumably) main.lua has finished being processed.

So the system event is not sent in your first example until *after* line 37 in your original program has processed. A lot of corona event handlers work this way - for example, if you change an objects x,y coords in an event handler, no change happens onscreen until after the handler exits (you can test this by making an infinite loop in an event handler after making a visual change to the display, and then running the app to see if it changed onscreen without ever exiting the event handler – it doesn’t).

The most common method I’ve seen to get around this is the old timer.performWithDelay() call. In your case, adding this to your original program would probably resolve the issue as well. Changing the end of your program to this would probably work:

[lua]

local function doStory()

   print(storyboard.state.data[1])

   – load first scene

   storyboard.gotoScene( “listGuitar”, “fade”, 1 )

end

timer.performWithDelay( 500, doStory )

[/lua]

The 500 millisecond delay is enough time for the lua interpreter to finish processing to the end of main, and then install the handler, and then to even call it as well.

Another way to put is that this allows the system event handler to fully install, and then (after 500 milliseconds), call the storyboard display stuff.

With this change, the sequence should be:

  • Main executes.

  • Immediately when main finishes executing, system event handler is installed

  • System event handler is called with “startup” event

  • 500 ms passes and doStory() gets called

Nice one, thank you!