Archive for the ‘AS3’ Category

Using AMF and RemoteObject without services-config.xml

Saturday, January 23rd, 2010

This article will be very short but I hope it will be very useful. The goal of this article is to show you how to use a RemoteObject without service-config.xml. The example in this post will be very simple, we will connect to a AMFPHP service and get a hello message from it.

First let’s see the service:

1
2
3
4
5
6
7
8
9
10
11
<?php
// hello.php
class Hello
{
	public function sayHello()
	{
		return "Hello back!";
	}
}
 
?>

Now in Flex all we have to do is to load a XML file ( channel.xml ) and read the channel from it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protected function addedToStageHandler( event :Event ) :void
{
 
	var loader :URLLoader = new URLLoader();
	loader.addEventListener( Event.COMPLETE, completeHandler );
	loader.addEventListener( IOErrorEvent.IO_ERROR, ioErrorHandler );
	loader.load( new URLRequest( "channel.xml" ));
 
}
 
protected function completeHandler( event :Event ) :void
{
 
	// Load info from XML
	var xml :XML = new XML( event.target.data );
	var amfEndpoint :String = xml..channel.( @id == "my-amfphp" ).@endpoint;
 
 
	// Create a AMF channel
	var channel :AMFChannel = new AMFChannel( "my-amf", amfEndpoint );
 
 
	// Add channel to our RemoteObject
	rmtObj.channelSet = new ChannelSet();
	rmtObj.channelSet.addChannel( channel );
 
}

Now if you use the loaded channel for all your RemoteObjects you don’t have to compile again your application if you decide to change your AMF endpoint, all you have to do is to edit the channel.xml file.

This is very useful when you upload your application to a server, you don’t have to compile again the application to work on different servers all you have to do is to use different channel.xml.

You can download the code here ( click to download ).

And this is all. If you have any questions post them here.

A Custom Drag-n-Drop List Control for Flex

Sunday, April 12th, 2009

Recently I have work on a custom component that extend the List class and add more functionalities to that class.The class do a lot of stuff but I decided to write a simple example for the blog that show just one functionality. The problem that this example solve is very simple:

“Make a list control that allow to drag only some of the list items”

The final result looks like this:

 

The steps to this are:

1) Create a list control and enable drag and drop

<mx:List
        id=”plList”
        width=”300″
        height=”300″
        dragEnabled=”true”
        dragMoveEnabled=”true”
        dropEnabled=”true”
        dragOver=”listDragOverHandler(event)” />

2) Create a XML that we will use as a dataProvider

<mx:XML id=”playlists”>
     <root>
          <pl name=”Playlist1″ icon=”myIcon” canMove=”1″ />
          <pl name=”Radio” icon=”myIcon2″ canMove=”0″ />
          <pl name=”Random” icon=”myIcon” canMove=”1″ />
          <pl name=”Best 90″ icon=”myIcon” canMove=”1″ />
          <pl name=”Custom” icon=”myIcon2″ canMove=”0″ />
     </root>
</mx:XML>

if you look at the XML you will see that a playlist contains 3 attributes. The name, icon and canMove. The canMove is the important attribute for us because this attribut will tell us if a item can move or not. Now that we have the XML let’s tell our list that we want to use this XML as a dataProvider and the name attribute as label:

<mx:List
        id=”usersList”
        width=”300″
        height=”300″
        dragEnabled=”true”
        labelField=”@name”
        iconField=”@icon”
        dataProvider=”{playlists.pl}”
        dragMoveEnabled=”true”
        dropEnabled=”true”
        dragOver=”listDragOverHandler(event)” />

3) Create a function that will be called when a list item is drag

private function listDragOverHandler( event:DragEvent ):void
{
        // with this call we are telling that we will
        // handle the drag
        event.preventDefault();

        // check to see if selected item can move
        var selectedItem :XML = XML(plList.selectedItem);
        var move :Number = Number(selectedItem.attribute(’canMove’));

        // if drag item can move
        if (event.dragSource.hasFormat(”items”) && move)
        {
                // Drag allowed
                event.currentTarget.showDropFeedback(event);
                DragManager.showFeedback(DragManager.MOVE);

                return;
        }

        // Drag not allowed.
        event.currentTarget.hideDropFeedback(event);
        DragManager.showFeedback(DragManager.NONE);
}

And this is all. If you have any questions post them here.

View the exampleView Source

Application Domains in Flex

Wednesday, March 4th, 2009

In this post I will try to explain the best I can why you need to know about application domains and how to use them. An application domain is the partition within which an application runs in Flash Player.  If you read the documentation you will see that application domain is a container for discrete groups of class definitions.

But what exactly an application domain does and when the understanding of application domain will helps you ? Usually there is just one application running which  implies the existence of only one application domain. Hance you will not notice or care about the application domain. However, when you load additional .swf files into your application you can create additional application domains for all the .swf files you load.

So let’s start. I will try to explain the application domain with an example. Let’s say we have an application named MyApplication that has a class HelloW with one function sayHello() and we want to load two .swf files in this application that has a class with the same name HelloW with one function sayHello() . When we load a .swf file, three possible things can occur:

1. The loaded .swf runs in an existing application domain.
2. The loaded .swf runs in a new application domain that is a child of an existing application domain.
3. The loaded .swf runs in a new application domain that is completely partitioned from all other application domains.

So let’s see for our example what will happen in each of the three cases :

1. The loaded .swf runs in an existing application domain

sameappdomain
Fig 1.0

You can load a swf in the existing application domain like this:

var context :LoaderContext = new LoaderContext( );
context.applicationDomain = ApplicationDomain.currentDomain;

var request  :URLRequest = new URLRequest(”SWF1.swf”);
var loader :Loader = new Loader( );

loader.load(request, context);

In our example, if we load our two swf files in the existing application domain the HelloW class from the first swf and HelloW class form the second swf will be lost against the HelloW class from the main application. Another problem will be that the SWFHelloW class from the second swf will be lost against the  SWFHelloW class from the first swf.  So, in the end, we will have :

- the HelloW class from MyApplication
- the SWFHelloW class from SWF1

Using this application domain we share code and use less memory, but in first SWF1 we have lost the HelloW class this can cause some big errors. All objects from SWF1 that use HelloW will now use HelloW from MyApplication and this class has different functionalities so this will cause some pretty nice errors. In the second SWF2 we have lost the HelloW and the SWFHelloW class. Which  can cause considerable  errors. In the end we will have an app with a lot of errors.

In order for this application domain  to work we must edit our example like this :

- the HelloW class from SWF1 and SWF1 must do the same things as HelloW class from MyApplication
- the SWFHelloW class from SWF2 must do the same things as SWFHelloW class from SWF1.

2. New application domain that is a child of an existing application domain

Neither of this  application domains is  good(suited) for our exemple. But let me show you what is the main difference between this application domain and the one before.

childappdomain1
Fig 2.0

In this application domain we lose the HelloW class but we don’t lose the SWFHelloW class from the second SWF.  We  achieve this application domain like this :

var context :LoaderContext = new LoaderContext( );
context.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);

var request  :URLRequest = new URLRequest(”SWF1.swf”);
var loader :Loader = new Loader( );

loader.load(request, context);

3.  New application domain

This is the solution for our example. Using this application domain in the end we will have:

- the HelloW class from MyApplication
- the HelloW class from SWF1 and SWF2
- the SWFHelloW class from SWF1 and SWF2

newappdomain
Fig 3.0

However, it is important to use these sorts of exclusive application domains only when necessary because they will increase memory usage. I hope this example has shown the importance of application domain and has given you a better understanding on what application domain you need depending on the result you want.