Thursday, October 16, 2008

Using a DataService in AIR to cache complex Data without LCDS Data Management (Part II)

Ok, as I said in the previous post, one of the most powerful features of a DataService in AIR is its ability to cache complex data either automatically or by calling DataService.saveCache(). Usually this is done by calling the fill() method on a DataService/Assembler while connected to LCDS and retrieving a Collection of managed Value Objects. In most cases the Value Objects have a nested hierarchy. To save this data for offline use in AIR you can simply set "autoSaveCache" to "true" on the DataService or you can call DataService.saveCache() explicitly.

I personally have a need to know when a fill() operation has finished downloading data to AIR from an Assembler. The ResultEvent associated with the AsyncToken on the fill() call is not a reliable indicator. Hopefully this will change in future versions of Flex/AIR/LCDS.

So, if you have a need to store data for offline use in AIR and can't use LCDS Data Management then simply use Remote Objects. This is how it works....

Create a DataService in AIR like this: (You can also just create this in ActionScript)

mx:DataService id="sampleDataService"

destination="sample"

autoCommit="false"

autoSaveCache="false"

autoConnect="false"

autoMerge="false"

cacheID="sampleId"

autoSyncEnabled="false"


Compile it against data-management-config.xml if you want but it doesn't matter because you will never connect this DataService to LCDS Data Management.

Here is the trick....

A DataService will store data to SQLite if you call DataService.saveCache(). The restriction is that it stores the data to disk but only associated with how you called "fill()". In order to get the data back while offline you simply need to call fill() again the same EXACT way with the same arguments.

When you call fill() on a DataService you will pass the method an ArrayCollection; at the very least. So, call fill() when you are disconnected. This will associate the ArrayCollection to the DataService's fill() call. Then you can make a RemoteObject call that returns an ArrayCollection of complex Value Objects. Add the contents of this RemoteObject Collection to the collection associated with the fill() call on the DataService. Then call DataService.saveCache().

You have successfully associated the data from the remote object call with the DataService and if you close the AIR Application, open it again and call fill() the same way you originally did the data is available for you to use offline.

In summary:
1. Create an ArrayCollection called "dataServiceAC"
2. Call DataService.fill(dataServiceAC);
3. Call RemoteObject.getData() and get an ArrayCollection called remoteAC.
4. Add the contents of remoteAC to dataServiceAC.
5. Call DataService.saveCache();
6. Close the application.

If you need the data again when you re-open the AIR Application simply call fill() again the same EXACT way you did before...

I have this up and working and it seems to be a good solution when you need an indication that your data in available or finished loading.

Warning!!! Caching data to SQLite through a DataService may have performance issues depending on the complexity of the data and the number of rows. I am noticing is gets slow at around 20K rows with simple data and at about 4K rows with complex data or data with a complex nested hierarchy.

No comments: