as3

Multi-Line Flex Label [MXML]

Just stumbled across this one while writing some mxml for a personal project and thought I would share.

Have you ever wanted to have multi-line text in your label component in spark and thought the following should work?

<s:Label text="I like text on the \n next line" />

But all it produces is:

Yep me too.

After some playing however I stumbled accross the following solution:

<s:Label text="I like text on the {'\n'} next line" />

It then produces the expected result:

Im just guessing but I suspect its something to do with the black art of the flex life cycle. By adding the {‘\n’} we are turning the property initialisation on the label component from a simple literal assignment into a delayed binding assignment and therefore gets parsed differently.

Just a guess, let me know if im way off.

Inputtie Development History – Networking

This is part two in my series of posts on the development history of Inputtie.

In this post I talk about the challenge of device discovery and networking in the Inputtie app.

Zero Configure Networking

I knew I wanted Inputtie to be as simple to get running as simply starting it up. For this to happen Inputtie would need to discover all other devices on the network also running Inputtie. So how to do this?

Well, as it happened I had been reading at the time about Apple’s Bonjour which was designed to do just what I needed. It is a combination of a multi-cast and DNS lookup service that allows it to detect other Bonjour capable devices on the network. Sounds perfect.

So I got to work on implementing their Java API. After many trials and tribulations I eventually had it working.. kinda. It was detecting other devices sure, but every now and then it would sporadically disconnect from the network. I couldn’t for the life of me work out why. I posted on forums and even tried to read the reams of source to see what was going on but alas to no avail.

After much deliberation I decided to look for another solution to the problem of Zero Conf. networking. Next up were a whole host of other attempts. I tried JmDNS which is was supposedly very similar to Bonjour. I also experimented with JGroups. I had limited success with all of them and in the end only really succeeded in wasting several months worth of development time.

The Solution

In the end the solution (and the one currently employed in Inputtie) was the simplest. After months of messing around with these libraries I had learnt quite abit about how they performed their magic. At the heart of it they either used multi-cast or broadcasting to announce a device on a network. Broadcasting can be thought of as a sort of sonar pulse. The broadcasting computer sends a message on a specific IP address then another device listens for the message and proceeds to open a Socket for a more private form of communication. From Wikipedia:

A broadcast address is a logical address at which all devices connected to a multiple-access communications network are enabled to receive datagrams. A message sent to a broadcast address is typically received by all network-attached hosts, rather than by a specific host.

I decided that if these libraries could use broadcasting for discovery then so could I and if I wrote it myself I could keep it simple. So I set to work coding an example in Java. In no time at all I had it running and surprisingly it worked! Sure it wasnt as robust as the established libraries, it didn’t handle devices disconnecting from the network, different network subnets or IPv6 but it was simple and at least it worked!

Broadcasting in Adobe AIR

As I mentioned in a previous post Inputtie went through many re-writes during development from its original form in Java through C++, C Sharp and finally Adobe AIR. With the latest (it was still in beta when I started development) version of Adobe AIR 2.0 several new APIs were made available for use, one of them being new classes designed specifically for peer to peer (P2P) networking. With these new APIs I believed I should be able to implement network broadcasting much in the same was I was doing in Java. Unfortunately however it seemed that Adobe was restricting the use of broadcast to their new P2P service Cirrus.

There was however another crucial API released with AIR 2.0; the NativeProcess API. With this a developer is able to easily execute and communicate with a program written in another language. What this meant for Inputtie was that I could write the user interface in AIR and then use NativeProcess to call Java code that would perform actions not available in AIR, such as Broadcasting. (incidentally it also is a great way to do multi-threading in Air ;) )

So the current solution in Inputtie is to use NativeProcess from AIR to communicate with a small headless (no user-interface) Java process that does the broadcasting and listening for broadcasts. Once the Java process detects an incoming broadcast it passes the information back to AIR.

EDIT: If anyone is interested in seeing the source to my previous (failed) attempt just drop me a comment or an email and I would be happy to share.

AS3, Dictionary & Weak Method Closures

This is going to be a technical post so those of you not of the code persuasion look away now..

Okay great, now those guys have gone I can get down to it.

Some of my recent work on the SWFt project has revolved around the use of Robert Penners AS3Signals. If you dont know what Signals are I strongly reccomend that you check out Roberts blog for more info. In brief, they are an alternative to the Events system found in Flash, based on the Signal / Slot pattern of Qt and C# they are much faster and more elegant (my opinion) than native events.

I have been trying to incorporate signals in SWft for both the elegance and performance gains that they bring, however there is an issue that was brought to my attention by Shaun Smith on the mailing list. The issue is that my current use of them will cause memory leaks.

I realised that this too would apply to the work I had been doing using the RobotLegs and Signals libraries. RobotLegs (for those of you that dont know) is an excellent Dependency Injection framework inspired by the very popular PureMVC framework. I have blogged before about its excellence. Signals have been incorporated into RobotLegs as a separate ‘plugin’ by Joel Hooks in the form of the SignalCommandMap. The SignalCommandMap does as the name implies, it allows you to map signals to commands so that whenever a mapped signal is dispatched then the corresponding command is executed.

Its a very nice, elegant, solution to RIA development. However there is one catch. I have so far been using signals such as:

  1. public class MyMediator extends Mediator
  2. {
  3. // View
  4. [Inject] public var view : MyView;
  5.  
  6. // Signals
  7. [Inject] public var eventOccured : ViewEventOccuredSignal;
  8. [Inject] public var modelChanged : ModelChangedSignal;
  9.  
  10. override public function onRegister():void
  11. {
  12. view.someSignal.add(eventOccured.dispatch);
  13. modelChanged.add(onModelChanged);
  14. }
  15.  
  16. protected function onModelChanged()
  17. {
  18. view.updateView();
  19. }
  20. }

So here we can see a typical use of Signals in a mediator. There are two things going on here that are of concern, lets break them down.

Firstly on line 12 we are listening to a signal on the view, then passing on the event directly to an app-level event, notice how nice and clean this is, this is what I love about using RL & Signals. Line 13 we are listening for an app-level signal for a change on the model then updating the view to reflect this.

It all looks well and good but unfortunately in its current state it could cause a memory leak. This is because we are listening to events on signals without then removing the listen. For example, we are listening to the app-level event on line 13 “modelChanged.add(onModelChanged);” so now the “modelChanged” signal has a reference to this Mediator. This will cause a leak when the View is removed from the display list. Normally the mediator would also be make available for garbage collection, however, because the singleton Signal has a reference to the Mediator it cannot be removed.

The same goes for line 12. Suppose the “ViewEventOccuredSignal” that is injected is not a singleton and is swapped out for another instance it could not be garbage collected as the “view.someSignal” has a reference to its dispatch function.

Realising this problem I knew that the solution was simply to be careful and add a “onRemoved” override function in my Mediator then clean up by removing the signal listeners. However I like the simplicity and beauty of current way of doing things so I started to wonder if there was another way.

I started thinking about whether I could use weak references with the Signal. If I could then I wouldnt have to worry about cleaning up as the Signal wouldnt store any hard-references to the functions and so the listener would be free for collection. After some digging however I realised that there was no option for weak listening in Robert Penners AS3Signals.

I thought to myself why the hell not? I knew that the Dictionary object in AS3 has an option to store its contents weakly so I thought so long as you don’t require order dependant execution of your listeners it should be possible to store the listener functions in a weakly referenced Dictionary.

It was at this point that I noticed Roberts post on the subject of weakly referenced Signals: http://flashblog.robertpenner.com/2009/09/as3-events-7-things-ive-learned-from.html. In it he references Grant Skinners post concerning a bug with storing functions in a weakly referenced Dictionary.

From Grant’s post:

Note that there is a known bug with Dictionary that prevents it from operating correctly with references to methods. It seems that Dictionary does not resolve the method reference properly, and uses the closure object (ie. the “behind the scenes” object that facilitates method closure by maintaining a reference back to the method and its scope) instead of the function as the key. This causes two problems: the reference is immediately available for collection in a weak Dictionary (because while the method is still referenced, the closure object is not), and it can create duplicate entries if you add the same method twice. This can cause some big problems for things like doLater queues.

This was starting to look bad for my idea. Me being me however, I thought I knew better, and that post was written pre Flash 10 so I thought to myself: perhaps its been fixed in Flash 10. So I set to work coding a simple example.

I created a very simple Signal dispatcher:

  1. package
  2. {
  3. import flash.events.EventDispatcher;
  4. import flash.utils.Dictionary;
  5.  
  6. public class SimpleDispatcher
  7. {
  8. protected var _listeners : Dictionary;
  9.  
  10. public function SimpleDispatcher(useWeak:Boolean)
  11. {
  12. _listeners = new Dictionary(useWeak);
  13. }
  14.  
  15. public function add(f:Function) : void
  16. {
  17. _listeners[f] = true;
  18. }
  19.  
  20. public function dispatch() : void
  21. {
  22. for (var o:* in _listeners)
  23. {
  24. o();
  25. }
  26. }
  27. }
  28. }

And a very simple listening object:

  1. package
  2. {
  3. public class SimpleListener
  4. {
  5. public function listen(d:SimpleDispatcher) : void
  6. {
  7. d.add(onPing);
  8. }
  9.  
  10. protected function onPing() : void
  11. {
  12. trace(this+" - ping");
  13. }
  14. }
  15. }

And then a simple Application to hook it all together:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  3. xmlns:s="library://ns.adobe.com/flex/spark"
  4. xmlns:mx="library://ns.adobe.com/flex/mx">
  5.  
  6. <fx:Script>
  7. <![CDATA[
  8. import mx.controls.List;
  9.  
  10. protected var _dispatcher : SimpleDispatcher = new SimpleDispatcher(true);
  11. protected var _listener : SimpleListener;
  12.  
  13. protected function onAddListenerClicked(event:MouseEvent):void
  14. {
  15. _listener = new SimpleListener();
  16. _listener.listen(_dispatcher);
  17. }
  18.  
  19. protected function onRunGCClicked(event:MouseEvent):void
  20. {
  21. try
  22. {
  23. new LocalConnection().connect('foo');
  24. new LocalConnection().connect('foo');
  25. }
  26. catch (e:*) {}
  27. }
  28.  
  29. protected function onDispatchClicked(event:MouseEvent):void
  30. {
  31. _dispatcher.dispatch();
  32. }
  33.  
  34. ]]>
  35. </fx:Script>
  36.  
  37. <s:VGroup width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
  38. <s:Button label="Add Listener" click="onAddListenerClicked(event)" />
  39. <s:Button label="Run GC" click="onRunGCClicked(event)" />
  40. <s:Button label="Dispatch" click="onDispatchClicked(event)" />
  41. </s:VGroup>
  42.  
  43. </s:Application>

So what I should expect to see from this example is that when I click “Add Listener” it should create a listener reference which will then listen for when the signal is dispatched and trace out a “ping”.

What actually happens is you get nothing. No trace out, despite the fact that there is clearly still a reference to the listener in the Application file.

So whats happening here? If you break into the debugger at the point that the listener is added then you get the following:

You can see that the type “MethodClosure” is added as the key to the dictionary rather than Function which is passed in. MethodClosure is a special native Flash Type that you dont have access to. It exists to resolve the issues we used to have in AS2 where passing a function of a class to a listener would cause the listener to go out of scope and other nasties. From the Adobe docs:

Event handling is simplified in ActionScript 3.0 thanks to method closures, which provide built-in event delegation. In ActionScript 2.0, a closure would not remember what object instance it was extracted from, leading to unexpected behavior when the closure was invoked.

..

This class is no longer needed because in ActionScript 3.0, a method closure will be generated when someMethod is referenced. The method closure will automatically remember its original object instance.

The only problem is that it seems that using a MethodClosure as a key in a weak dictionary causes the MethodClosure to have no references and hence be free for garbage collection as soon as its added to the Dictionary which is not good :(

So thats about as far as I got, I have spent a few evenings on this one now and I think im about ready to call it quits. I had a few ideas about creating Delegate handlers to make functions very much in the same way as was done in AS2 but then I read this post: http://blog.betabong.com/2008/09/26/weak-method-closure/ and the subsequent comments and realised it probably wasnt going to work.

I also had an idea about using the only other method of holding weak references the EventDispatcher class. I thought perhaps somehow I could get it to hold the weak references then I could loop through the listeners in there calling dispatch manually. Despite “listeners” property showing up in the Flex debugger for an EventDispatcher you dont actually have access to that property unfortunately so hence cant get access to the listening functions. Interestingly however the EventDispatcher uses “WeakMethodClosure” object instead of the “MethodClosure” object according to the debugger.

Well I guess for now Ill have to make sure I code more carefully and unlisten from my Signals ;)

 Scroll to top