Saturday 16 July 2011

Preventing browser from closing your Flex Application

At work recently a bug came my way saying that if a user closed the browser mid way through a certain process it would corrupt the database and not allow the user to re-open that task.

Now obviously there are a few issues here:

  • closing the browser did nothing to the database, it just meant that the flex application was not given the opportunity to clean up and the data on the server was left in a state that could not be re-loaded
  • whatever calls a client makes to the server the database should never get corrupted and should always be in a re-loadable state!

Easy then, just pass the bug to the java team!

There has been a long standing nice to have task though that we prompt a user when they try to close the browser when they have unsaved data. This bug made it seem like a good idea to look into this.

I knew the basics behind this (use JavaScript to call a flex function) but have never actually done it. I also knew that there was a way of having the flex app inject the JavaScript into the HTML page. I did a bit of googleing and found these 2 bog posts:

And from what I learnt I came up with this:

The way this works is that when you try to close the browser the onbeforeunload event is fired. This calls the JavaScript function confirmClose which in turn calls the ActionScript function getCloseConfirmMessage. We allow JavaScript to call this function by calling

ExternalInterface.addCallback( "getCloseConfirmMessage", closeConfirmMessage )

within our flex app. This flex function either returns a message to display in the browser dialogue box (the reason why you can’t close the browser for example) or null if you are allowed to close the browser – in which case the browser just closes with no confirm box.

I really like the fact that all this code is inside the swf. I don’t have to make sure that I am deploying the correct html file along side my swf. Any html file will work.

The app I link to above is just an example of how to get it to work. In the real application I have put all of this in a parsley managed class. Parsley is used to dispatch a cancellable event. Any area of the app that has unsaved data for example can cancel the event and provide a message. This message is then returned to JavaScript to be displayed.

I have also added a function call that gets fired when the browser is actually closed. Again this fires a Parsley message and anything that is interested can use this to tidy up – for example close streams that the app is subscribed to.

Thanks to the 2 guys who wrote the 2 blog posts above.

Saturday 2 July 2011

Spark DataGrid slow?

I am currently in the process of writing a little Air app for myself. I doubt it will be any use to anyone else but I am enjoying writing it and it will be useful for me.

The app collects data (ok, my weight!) and displays it in a graph over time. I can also add targets and plots the target weight against actual – you get the idea.

The app uses charts and a DataGrid for this.

I want to also build the app for mobile so that I use it on my phone and this gives me a bit of a problem. Adobe recommend not to use the spark DataGrid in mobile apps and does the same for the charts.

In the desktop app that I am working on at the moment the line chart is super fast but I have been very disappointed in the performance of the DataGrid. At the moment I have ONE row in the DataGrid with 5 columns.

It takes 300 ms to create this!

What’s even worse is that after it’s created it still takes 150 ms to show the grid again after the view is hidden.

How can the performance be SO bad? Any suggestions about what else I can use? Has anyone else found this?

This is on Flex 4.5.0 build 20967 running in debug mode.