More Efficient Facebook / Flex API – using XML and e4x instead of ActionScript Objects

I’m a big fan of the e4x implementation in Flex. Elegant and powerful, it allows a versatile and dynamic way of passing data across components. In this post, I’ll describe how to access data in this raw XML format within the newly updated Facebook / Flex API.

If you’re a fan of the way Flex handles XML via e4x, you’re probably disappointed that all the new examples posted on the Adobe developer connection create new ActionScript objects to represent facebook instances. In this post, I’ll briefly describe how to work with XML instances directly and describe some of benefits of this approach.

Let’s look at the second example provided on the Adobe website, in it, you will find the following code:

private function handleGetAlbumsResponse(e:FacebookEvent):void {
   var albumsResponseData:GetAlbumsData = e.data as GetAlbumsData;

   if (!albumsResponseData || e.error){ // an error occurred
       status.text = "Error";
       return;
    }
 
   facebookPhotoAlbums = new ArrayCollection();
   for(var i:int = 0; i < albumsResponseData.albumCollection.length; i++){
   facebookPhotoAlbums.addItem(albumsResponseData.albumCollection.getItemAt(i));     
}

I was confused by the casting to ArrayCollection, so I looked at the definition of albumCollection, it a subclass of FacebookArrayCollection, which was a class written for the API. The problem here is that Flex components don’t know how to bind FacebookArrayCollection elements ( you get a [object data] list if you try ). So to make the example simpler for ActionScript developers, this Array was simply cast again as an ArrayCollection ( code in red ).

This seems terribly inefficient.

Let’s look at the XML version of the same code:

// Remember to change the declaration of facebookAlbums to
// [Bindable] facebookAlbums : XMLListCollection;
private function handleGetAlbumsResponse(e:FacebookEvent):void {
   if( e.success )
      facebookPhotoAlbums = new XMLListCollection( ( e.data.rawResult as XML )..album );
   else
      status.text = "Error";
}

Here, I simply took the raw result returned by the REST call, and said ‘get me all the child nodes named album’!

While this XML might seem daunting, it actually fits closer to the Developer tools provided by Facebook. Instead of guessing which methods to call or use autocomplete in Flex Builder, I can simply test out my Rest or FQL calls and access the node I need using the developer tool.

If you’re interested ( and who wouldn’t be ), the XML for the album looks something like this:

<album>
 <aid>90210496655028401</aid>
 <cover_pid>90210496691509407</cover_pid>
 <owner>21003768</owner>
 <name>masLONDON</name>
 <created>1238365415</created>
 <modified>1238372207</modified>
 <description/>
 <location>london</location>
 <link>http://www.facebook.com/album.php?aid=2257073&amp;id=21003768</link>
 <size>43</size>
 <visible>everyone</visible>
</album>

Something Adobe seems to do a lot is to cast things into objects without the need to do so. This happens in the design of BlazeDS and Cairgorm. But for Facebook data, you lose a lot of power the moment you decide to convert into objects. One of the nicest things about Flex is the way XML gets treated as first class citizens, and it’s a shame that few of the tutorials on this take advantage of this.

With XML, I could easily show only the albums with more than 40 pictures:

      facebookPhotoAlbums = 
               new XMLListCollection( ( new XML( e.data.rawResult ) )..album.( size > 40 ) );

Or instead get a list of album names

      facebookPhotoAlbums = new XMLListCollection( ( new XML( e.data.rawResult ) )..name

Hope this was useful. Remember to visit Empora

CAUTION: Remember to set the right namespaces, or your results will not work —
namespace fb = “http://api.facebook.com/1.0/&#8221;;
use namespace fb;

EDIT: Sometimes casting e.data.rawResult to XML yields a null value, but new XML( e.data.rawResult ) works fine. I’ve updated this post to show this.

5 thoughts on “More Efficient Facebook / Flex API – using XML and e4x instead of ActionScript Objects

  1. Matt Rooney

    Hi,

    Can you post the complete second example (the album lister) modified to use xml. I am not able to figure out how to set the namespace to have an XMLListCollection act as a dataprovider for the album. It works fine when the XMLListCollection is just simple data list like ..name but when it is a collection like ..album, I see nothing in the grid.

    I tried with a mx:List and I can see all the fields if i put {data} in my renderer but if i put {data.name} I see nothing.

    Thanks.

    Reply
  2. Matt Rooney

    Thanks for the info. data.*:: works fine for some component but for datagrid I figure out that the best solution is to remove the namespace from the xml (otherwise you have to create a labelFunction which is not always the best way to go (because you have to create also a custom sort function, etc)).

    Here is how I done it for interested people:

    I create a private variable in the main section that define the regular expression to avoid creating it at each conversion:

    private var xmlnsPattern:RegExp = new RegExp(“xmlns=[^\”]*\”[^\”]*\””, “gi”);

    And when I create the collection, I remove the namespace right from the rawresults like:

    facebookPhotoAlbums = new XMLListCollection( ( new XML( e.data.rawResult.replace(xmlnsPattern, “”) ) )..album);

    Reply
  3. Jonas De Smet

    I prefer to use Objects but I don’t use the standard calls from the API, because you mostly only recieve UID’s in calls.
    When I want to recieve something I perform a FQLQuery with return-format JSON so I don’t need to use a different namespace and I can easily use the Array-sort functions on the result.
    Unfortaintly there aren’t good examples on how to do it, it’s trial and error untill you find the easiest way🙂

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s