Home >
Component Architecture for Facebook Applications
In the last tutorial we discussed the new library that was released by Adobe. The new library from Adobe fits much more naturally into the whole architecture of Facebook applications that are built using the Flash platform. We need to know that the previous approach using the PHP library is not useless. In order to create stable and useful Facebook applications we need to know about many ways to achieve the same goal.
When you start with Facebook application development you will encounter a lot of situations where you will need to have alternate ways to solve problems. When dealing with application development, we always have to know that decisions made at the start of the project are not written in stone, but rather written in the sand. Basically, this means that we never need to rely on the decision made at the start of the project, mentally we must be prepared for the changes that may affect our projects. In our case, suppose we work on a Facebook application that is based on Adobe's library. OK, the library is really fancy and fit very well into our apps, but suddenly, when the project is finished, the project manager knocks on your door and says that there is a database of Facebook users that need to be imported and its in MySQL. Well, now the knowledge from previous articles comes in handy and you simply implement a PHP class file with AMFPHP that retrieves the users from the MySQL table and the result is send to Flash in a format that is understandable by ActionScript. Cool, problem solved, and your boss agrees that you should get a higher salary. If you followed the series from the start then you are on the way to being able to create truly cutting-edge Facebook apps as we have discussed have to grab results from DB and we also make use of the ActionScript library.

Find the rest of this series on the series page.
Our goal for this article is to demonstrate how to create components that rely on Adobe's ActionScript library. For the beginning, we will create a simple DisplayStatus component that can be further customized. The great thing about the components is that it can be placed anywhere on the stage and customized. The component will appear in the components panel and any number of instances can be placed on the stage.
Let's get started!
Here is the image of the final result:
Open Flash and reopen the fla we worked on previously. There we have the stuff from the previous sample. Remove all components from the stage and the code from the first frame.
Go to File -> New -> ActionScript File
For now, just add the following lines of code:
package facebookUI{
public class FacebookUIComponent{
function FacebookUIComponent() {
trace("Hi my name is... " + this);
}
}
}
A typical component structure for ActionScript 3.0 components consists of 2 frames. One frame for the avatar, the other frame for the assets. In ActionScript 2.0 we had to place a stop() command at the first frame to prevent the movieclip from looping, in ActionScript 3.0 this is no longer necessary.
So, the frame structure looks like this:
On the avatar layer in the first frame, place a rectagle without fill (hairline line style!) 400 x 22. This will act as the frame size for the component when placing on the stage. On the Assets layer, we will place the Facebook API SWC from the components panel. In the previous article we discussed how to place the SWC in the proper folder.
Now, since the Facebook API will be packed and exported together with the component, we need to check the options for the Facebook swc that was placed on the stage. Open the library of the fla, right click the Facebook swc and choose "Linkage...". Make sure the following options are checked:
So for this example we packed all the stuff we need in order for this component to run. Lock the avatar layer and leave the assets layer unlocked.
Extending the UIComponent class
As we already know, the UIComponent class contains all the logic we need to handle the resizing , positioning and drawing the component. In our example we will use the component architecture to make our lives and Facebook application development easier and more fun.
Here is the original class code we created:
package facebookUI{
public class FacebookUIComponent{
function FacebookUIComponent() {
trace("Hi my name is... " + this);
}
}
}
import fl.core.UIComponent;
import flash.text.*;
public class FacebookUIComponent extends UIComponent{
private var _status_txt:TextField = null;
function FacebookUIComponent() {
}
When extending the UIComponent there is no need to call the super() method. Now there is the important config() method that needs to be overridden. For all of you who are not familiar with the UIComponent architecture, it's important to know that this method is automatically called after the style and invalidation infrastructure for the component is initialized. This is the place to create display objects and add them to the display list, not the constructor. We can do some neat things here!
Since we are creating a component that will display only the status of the Facebook user, we only need a simple text field that will be resized accordingly. Our overridden configUI() looks like this:
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
_status_txt = new TextField();
addChild(_status_txt);
_status_txt.text = "Hello....";
}
package facebookUI{
import fl.core.UIComponent;
import flash.text.*;
public class FacebookUIComponent extends UIComponent{
private var _status_txt:TextField = null;
function FacebookUIComponent() {
//const. stays empty
}
//here we place all the necessary assets on the stage
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
// dynamically create myMenuBar
_status_txt = new TextField();
addChild(_status_txt);
_status_txt.text = "Hello....";
}
}
}
Right-click on the UserStatus component right in the library and select "Linkage", make sure the following definitions are set:
Click OK and drag one instance onto the stage (the main timeline, not the timeline of the UserStatus component), like on the image below:
Compile the example, and on the screen the following should appear:
Nothing fancy, but if there were no errors, we did a great job until now.
So how are we going to connect this to Facebook?
First of all, the sample will run again on the standard Facebook canvas. In the previous example we worked on the desktop AIR sample just to demonstrate the desktop abilities of the Facebook + ActionScript combination. Just as we did in the first articles, the swf need to be uploaded again to the web server.
So, when uploaded here is the same swf inside the Facebook canvas:
Cool, now we can start modifying the class file to work with the Facebook API. For this, we will use the library by Adobe. Since we worked in the previous sample with the library, we know the basics.
Open the class file FacebookUIComponent that we previously worked on. After the existing import statements, add the following statements:
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.data.friends.*;
import com.facebook.commands.users.*;
import com.facebook.commands.friends.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
Since it is a Facebook application that runs in the application canvas, we do not need to call the login() methods we previously had. We can directly start calling Facebook methods. First we must declare the variables that are needed:
private var fbook:Facebook;
private var session:FacebookSessionUtil;
private var user:FacebookUser;
Then, we cannot use the configUI() method to instantiate the Facebook classes since we want the configUI() to handle only the user interface objects. We use that method, it's not forbidden, but for the sake of better code maintenance, let's create a separate method for Facebook class instantiation:
private function initFB():void {
// instaniate
session = new FacebookSessionUtil(" YOUR_API_KEY", "YOUR_SECRET", stage.loaderInfo);
fbook = session.facebook;
//make the call to get the status
var call:GetInfo = new GetInfo([fbook.uid],[GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
OK, but somewhere the initFB() function needs to be called and this will be done in the constructor:
function FacebookUIComponent() {
initFB();
}
And finally, there is the onInfo function that receives the Facebook results:
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_status_txt.text = user.status.message;
}
Since we got the FacebookUser object, we simply read what we need, this is the status message. :-) Let's compile and upload, here is the result:
The result may be a bit modest, but we just created a functional Facebook Flash component!
Here is the complete class code:
package facebookUI{
import fl.core.UIComponent;
import flash.text.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.data.friends.*;
import com.facebook.commands.users.*;
import com.facebook.commands.friends.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class FacebookUIComponent extends UIComponent{
private var _status_txt:TextField = null;
private var fbook:Facebook;
private var session:FacebookSessionUtil;
private var user:FacebookUser;
function FacebookUIComponent() {
initFB();
}
private function initFB():void {
session = new FacebookSessionUtil(" YOUR_API_KEY", "YOUR_SECRET", stage.loaderInfo);
fbook = session.facebook;
var call:GetInfo = new GetInfo([fbook.uid],[GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
_status_txt = new TextField();
addChild(_status_txt);
_status_txt.text = "Hello....";
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_status_txt.text = user.status.message;
}
}
}
Taking care of little things
Since we made the call we have to make sure of little things. Right now the componentis a bit raw. We will have a lot of components on our stage and imagine that for every component we have to define the API key and the secret. That would be ambiguous and would not make any sense. The best solution is in fact very simple.
Here is the overview:
What does this mean? We really do not want every component that we place on the stage to make the session variable. This would be a total waste of memory and it would also hurt the DRY principle, this means that we do not want to repeat ourselves in the code. Once one session is enough for us and it will be passed to every component. Then, the component itself will do with the session object what it needs to do...in this case make a call to load the user status, the other component can use the session to display the albums and send notifications etc. Everything is much easier to maintain when it is not duplicated, like our session object.
So, in order for this to work we need to modify the class we FacebookUIComponent:
package facebookUI{
import fl.core.UIComponent;
import flash.text.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.data.friends.*;
import com.facebook.commands.users.*;
import com.facebook.commands.friends.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class FacebookUIComponent extends UIComponent{
private var _status_txt:TextField = null;
function FacebookUIComponent() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
_status_txt = new TextField();
addChild(_status_txt);
}
public function loadStatus(fbook:Facebook) {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_status_txt.text = user.status.message;
}
}
}
The next thing we need to do is go back to our main timeline and place those lines of code in the first frame:
import com.facebook.Facebook;
import com.facebook.utils.FacebookSessionUtil;
var fbook:Facebook;
var session:FacebookSessionUtil = new FacebookSessionUtil("MY_API_KEY", "MY_SECRET", loaderInfo);
fbook = session.facebook;
status1_mc.loadStatus(fbook);
The only thing that is left to do is to select the UserStatus movieclip on the stage and give it the instance name status1_mc. You can see that we reference it in the code. When compiled, the result is pretty much the same:
This time the architecture is much more flexible. First we cleared the contructor:
function FacebookUIComponent() {
}
Then we completely removed the initFB() function since we will not allow the component to handle the session stuff. The configUI() function is the same, only the loadStatus function is new:
public function loadStatus(fbook:Facebook) {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
So, as we can see, the method receives the Facebook object that containts all the session data. The we make our call to the Facebook API and retrieve the status. Throughout the application there will be only one session object, no need to create it for every component.
At the end, we really do not want the class to be called FacebookUIComponent. I named it this way to better understand the process of UIComponent inheritance. Rename the whole ActionScript class file to UserStatus.as, and the class name should now match the name.
package facebookUI{
import fl.core.UIComponent;
import flash.text.*;
import com.facebook.data.users.GetInfoData;
import com.facebook.utils.FacebookSessionUtil;
import com.facebook.data.users.FacebookUser;
import com.facebook.data.users.GetInfoFieldValues;
import com.facebook.data.friends.*;
import com.facebook.commands.users.*;
import com.facebook.commands.friends.*;
import com.facebook.net.FacebookCall;
import com.facebook.events.FacebookEvent;
import com.facebook.Facebook;
public class UserStatus extends UIComponent{
private var _status_txt:TextField = null;
function UserStatus() {
}
override protected function configUI():void {
// always call super.configUI() in your implementation
super.configUI();
_status_txt = new TextField();
addChild(_status_txt);
}
public function loadStatus(fbook:Facebook) {
var call:GetInfo = new GetInfo([fbook.uid], [GetInfoFieldValues.ALL_VALUES]);
call.addEventListener(FacebookEvent.COMPLETE, onInfo);
fbook.post(call);
}
private function onInfo(e:FacebookEvent):void{
var user = (e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
_status_txt.text = user.status.message;
}
}
}
Believe it or not, we did a great job until now. We defined a Facebook component architecture that is flexible and that will prove useful when our Facebook applications get more complex. In such situations, the DRY priciple is always useful. We use only one Facebook session accross the whole application and pass it to specific components that accomplish specific actions. In the next article we will discuss the profile pic component that is based on the architecture that was described in this article. You may ask yourself why we made so many code changes in this article and why we didn't simply go through the last sample where everything works and is correct? It's because I wanted you try the hard way and create code that works (FacebookUIComponent.as) but is not perfect and lacks flexibility. I really wanted you to make the changes and see what benefits the application design will have.
I hope next week you will tune in where we discuss the component for profile pictures.
To view the entire series please visit http://www.insideria.com/series-facebook-dev.html




Facebook Application Development
If anyone gets the following error: 1017: The Definition Of Base Class UIComponent Was Not Found, see the following
Solution.
You will need to add
$(AppConfig)/Component Source/ActionScript 3.0/User Interface
to your AS3 application settings.
Can you tell me how can I implement the facebook component to my ActionScript 2.0 project
Can you tell me how can I implement the facebook component to my ActionScript 2.0 project
Can you tell me how can I implement the facebook component to my ActionScript 2.0 project
what is the "standard Facebook canvas" for you?? do you mean FBML ??
Hello everyone, I enjoy so much these tutorials.
I want to ask if I can put the information of the status in a Dynamic Text. If this is possible, what can I do?
Thanks if you can help me.
Hello everyone, I enjoy so much these tutorials.
I want to ask if I can put the information of the status in a Dynamic Text. If this is possible, what can I do?
Thanks if you can help me.
Thanks again for the detailed explanation, as per usual I can't fault it. I love the Facebook API, and particularly like doing this with it with your help! lightweight rucksack
Thanks for all the tutorial, but I have a problem when I create the UserStatus Component
it say me that the class facebookUI.FacebookUIComponent must be a subClass of flash.display.MovieClip because it's link with a symbol of this libray.
Where I make the fault?
Thanks by by.
I'm sorry :P I didn't place the other components in the fla thanks a lot.