AS3 event framework-Signals

Source: Internet
Author: User

This article details what the AS3 Signals of Robert Penner is and how to use it to make communication between objects faster. It prevents you from using the conventional event mechanism of ActionScript and requires less code.
We will use examples to understand different types of signals, so as to show you how to apply signals in actual projects. I hope you will enjoy the object communication convenience brought by AS3 Signals like me. One benefit is that Signals can easily master applications. You will implement it soon, and it will bring more convenience. Let's get started!
It is a good idea if you want to do it yourself. You can go to GitHub and download the AS3 Signals SWC file and create a project in your favorite IDE (for example, I will select FDT) and import the SWC file to your project.
What is AS3 Signals?

Signals is a new mechanism of AS3 events, inspired by C # events and signals/slots in Qt. (Robert Penner)
Robert Penner promotes Signals as "thinking independently from the incident ". It is used to describe Signals as a lightweight and forced AS3 communication tool.
This has already explained some of the details. A more detailed explanation is:
Signals is a framework that can replace AS3 built-in events to some extent.
It integrates C #'s excellent signals ideas and functional event ideas in APIs. It is faster than built-in events, and it also lacks a lot of dull code. What's even more valuable is that it can also use built-in events, which are four times faster than built-in events.

What is Signal?

A Signal is essentially a micro-specific dispatcher for an event, with its own array of listeners.
The basic concept of a Signal is to convert it into a specific event/signal member in a class instead of using a string-based channel similar to built-in events. This means that we developers have more control over how to connect and communicate with objects. We no longer need string variables to represent our Signals. Signals can be expressed as real objects.
If you are already an ActionScript developer, sometimes it is quite painful to create a custom event subclass in your project. Define constants, define events, and so on. Add listeners, remove listeners, and always inherit EventDispatcher in your dispatch class. You will find that Signals will make it easy in a short time.

Signal Basics
Start with the most basic Signal. For example, we use it to replace a custom AS3 event. Signal can be simply regarded as an object. A basic Signals is a public attribute of your distribution class.
The first advantage we can find is that we no longer have to extend the EventDispatcher class to implement the dispatch class just like using the built-in Event System.
Let's take a look at a simple AlarmClock example to understand the syntax.
[Insideria. basicSignal. AlarmClock. as]

 package insideria.basicSignal {         import org.osflash.signals.Signal;          public class AlarmClock          {                  public var alarm:Signal;                    public function AlarmClock()                   {                           alarm = new Signal();                   }                                    public function ring():void                  {                           alarm.dispatch();                   }          }}

With AlarmClock, we first instantiate it. Then we will use the add () method of the public attribute alarm, that is, our Signal, to add a listener named onRing. Then we need the alarm to ring, so we call its ring () method. This is easy. If you publish a program, you will see "Wake up!" on the console !" .
PASS Parameters
The basic Signal skill is more than that. I believe you are eager to know how we use Signal to pass parameters. This is also very simple. Let's update the AlarmClock class so that we can pass time to our WakeUp class.

[Insideria. basicSignalArguments. AlarmClock. as]

package insideria.basicSignalArguments {         import org.osflash.signals.Signal;          public class AlarmClock          {                  public var alarm:Signal;                    public function AlarmClock()                   {                           alarm = new Signal(String);                   }                                    public function ring():void                  {                           alarm.dispatch("9 AM");                   }          }}

So all we have to do to deliver a stronugly-typed argument (you can also deliver untyped arguments) via our Signal is defining the type in the Signals constructor and dispatching whatever we want in the dispatch () method. you can pass multiple arguments of same or different type by separating them with a comma.

Because our change is to pass a mandatory Type parameter through our Signal (you can also pass a non-class parameter), it will be declared in the Signal constructor, use dispatch () to dispatch any parameters you want to pass. You can also pass multiple parameters of the same type or different types and separate them.

alarm = new Signal(String, Number, int, uint, Boolean);alarm.dispatch("9 AM", 45.4, -10, 5, true);

Now let's take a look at how our main program interface traces time.
[Insideria. basicSignalArguments. WakeUp. as]

package insideria.basicSignalArguments{         import flash.display.Sprite;          public class WakeUp extends Sprite         {                  private var alarmClock:AlarmClock;                    public function WakeUp()                   {                           alarmClock = new AlarmClock();                           alarmClock.alarm.add(onRing);                           alarmClock.ring();                   }                    private function onRing(time:String):void                  {                           trace("Wake up! It's already " + time);                   }          }}

The listener of Signal must now add a parameter. Otherwise, the compiler will throw a parameter error. For clarity, we also call it time. Note that this parameter must also declare a category. Now when we run the program, the console will say "Wake up! It's already 9 AM ".

Add and remove Signals
In actual programming, you often encounter a situation where you only need to activate an event once and then destroy it immediately. Compared with built-in events, Signals provides an easy way to do this without having to write that bunch of annoying code, such as like addEventListener (...), removeEventListener (...).

So let's modify the WakeUp, replace the add () method with addOnce (), and let it capture Signal only once.

alarmClock.alarm.addOnce(onRing);

In this way, the listener will be executed only once and then automatically removed. If you are using the add () method, you need to remove the listener. You can use the remove (listener) method or the removeAll () method of Singnal, if multiple listening objects are attached to a specific Singnal. Let's see what it looks like:
AlarmClock. alarm. remove (onRing );
AlarmClock. alarm. removeAll ();
So far, we have learned many frequently used features. I guess you will also be curious about how to get more information from Signal. For example, in a built-in event, it tells us everything about the target source. Signal can do the same. Let's continue.

DeluxeSignal and GenericEvent
DeluxeSignal is a step closer to the built-in event. DeluxeSignal allows us to access the target, especially the Signal itself. So we can operate on both. Of course, DeluxeSignal also has basic Signal functions. Now we will update our AlarmClock and use DeluxeSignal in combination with GenericEvent. You will learn about GenericEvent in this process.

[Insideria. deluxeSignal. AlarmClock. as]

package insideria.deluxeSignal{         import org.osflash.signals.DeluxeSignal;         import org.osflash.signals.events.GenericEvent;          public class AlarmClock          {                  public var alarm:DeluxeSignal;                  public var message:String;                    public function AlarmClock()                   {                           alarm = new DeluxeSignal(this);                           message = "This is a message from our AlarmClock";                   }                                    public function ring():void                  {                           alarm.dispatch(new GenericEvent());                   }          }}

We created a public attribute of DeluxeSignal, instantiated it in the constructor, and passed this to the constructor of DeluxeSignal. In this way, DeluxeSignal will know AlarmClock. We also created a public attribute of message, which can be accessed by the listener later.
This is an example of how to use GenericEvent to pass multiple parameters. Speaking of GenericEvent, let's look at the ring () method. The distribution of DeluxeSignal is the same as the basic Signal we used previously, but this time we passed an instance of GenericEvent to it. This GenericEvent will include the source of Signal and information about it. Let's see how to access this information in the main program file.
[Insideria. deluxeSignal. WakeUp. as]

package insideria.deluxeSignal {         import org.osflash.signals.events.GenericEvent;         import flash.display.Sprite;          public class WakeUp extends Sprite         {                  private var alarmClock:AlarmClock;                    public function WakeUp()                   {                           alarmClock = new AlarmClock();                           alarmClock.alarm.add(onRing);                           alarmClock.ring();                   }                    private function onRing(event:GenericEvent):void                  {                           trace(event.target);                           trace(event.signal);                           trace(event.target.message);                   }          }}

Only the listener has changed. The listener now receives the GenericEvent parameter, which we pass through the AlarmClock class.
Remember that we get information from here. Now we can trace the target and other attributes such as message, as we do in the built-in events. The only special thing is that we can also access the Signal object for dispatching events in the AlarmClock class.

We have learned two types of Signal. Next, let's take a look at how to use built-in events through AS3 Signal.
NativeSignals
In the end, AS3 Signals can serve as a complete alternative to built-in events, which allows developers to access built-in events. Robert Penner is also very careful about this task.
Because I always like to give some practical examples, because let's first look at how NativeSignal loads another SWF file at runtime.
The first thing we need to do is create a SWF for loading.

Because we need to use the ADDED_TO_STAGE event in the following class, first pay attention to the use of the NativeSignal class.
[Insideria. nativeSignals. AddToStage. as]

package insideria.nativeSignals{         import org.osflash.signals.natives.NativeSignal;          import flash.display.Sprite;         import flash.events.Event;          public class AddToStage extends Sprite          {                  public function AddToStage()                  {                           var added:NativeSignal = new NativeSignal(this, Event.ADDED_TO_STAGE, Event);                           added.addOnce(onAdded);                   }                    private function onAdded(event:Event):void                   {                           graphics.beginFill(0xCCCCCC);                           graphics.drawRect(0, 0, 100, 100);                           graphics.endFill();                   }          }}

As you can see, we have created a local NativeSignal. The first parameter is the target this, the second parameter is the event we want to use, and the third parameter is also an event class. Like the basic Signals we discussed earlier, we use the addOnce method to only execute Signals once. When Signals is executed once, we don't need to worry about how to clear it.
Sible to perhaps click on.
Now, just as we are using built-in events, we have created an onAdded callback function. The execution function receives an Event parameter of the Event type. Make sure that the parameters passed in the execution function are consistent with the event category in the NativeSignal instance.
In our onAdded callback function, we just drew some random images to ensure that they are indeed loaded into other files. Of course, we can use NativeSignal to do more things. For example, some visual objects can be clicked.
Now, create the SWF file we want to use.

Create loading class
We have created a visual class that extends from Sprite. Next we need three private attributes to include our native Signals. Don't be confused by these private attributes-they don't need to be accessed externally like the basic Signal.

Private var loadedSignal: NativeSignal;
Private var progressSignal: NativeSignal;
Private var faultSignal: NativeSignal;
Next we need to load the Basic settings of the binary file. Therefore, we created a URLRequest, a Loader, and an EventDispatcher pointing to Signals.

Var request: URLRequest = new URLRequest ("AddToStage.swf ");
Var loader: Loader = new Loader ();
Var signalTarget: IEventDispatcher = loader. contentLoaderInfo;
Now we will use the NativeSignal class to create a local Signal that serves our loading events, progress events, and default events. We will save the contentLoaderInfo attribute of our loader instance as an IEventDispatcher variable.

LoadedSignal = new NativeSignal (signalTarget, Event. COMPLETE, Event );
LoadedSignal. addOnce (onLoaded );

ProgressSignal = new NativeSignal (signalTarget, ProgressEvent. PROGRESS, ProgressEvent );
ProgressSignal. add (onProgress );

FaultSignal = new NativeSignal (signalTarget, IOErrorEvent. IO_ERROR, IOErrorEvent );
FaultSignal. addOnce (onFault );
Note the following when creating the syntax of such a local Signal object: The first parameter is the target, the second is the event with a constant, and the third is the event class. In addition, the parameter category in event handler must be consistent with that used in the native Signal object. The last point is to note that the loading has started.

Loader. load (request );

Next, we need to set the method for processing Signals.

private function onFault(event:IOErrorEvent):void {         trace("Something went wrong!");}private function onProgress(event:ProgressEvent):void {         trace((event.bytesLoaded / event.bytesTotal) * 100);}private function onLoaded(event:Event):void {         progressSignal.removeAll();         addChild(event.target.content);}

In this way, we can respond when an error occurs during loading. We can display the progress during loading, add the content to the display list after completion, and remove progress Signal, because we no longer use it. If you have understood the concepts of using add () and addOnce (), we should obviously use addOnce in fault and complete, because they only need to be executed once. Add () should be used in progress, because it will be executed many times before loading is complete.
If you run the program, you will see a x pixel square in the upper left corner. If Something goes wrong, the console will prompt "Something went wrong !", Because we have hardcoded it into the class. If you encounter an error, make sure that the link path in the URLRequest instance actually points to the SWF file path we want to load.

The complete code is as follows:

[Insideria. nativeSignals. Loading. as]

package insideria.nativeSignals{         import org.osflash.signals.natives.NativeSignal;          import flash.display.Loader;         import flash.display.Sprite;         import flash.events.Event;         import flash.events.IEventDispatcher;         import flash.events.IOErrorEvent;         import flash.events.ProgressEvent;         import flash.net.URLRequest;          public class Loading extends Sprite          {                  private var loadedSignal:NativeSignal;                  private var progressSignal:NativeSignal;                  private var faultSignal:NativeSignal;                    public function Loading()                  {                           var request:URLRequest = new URLRequest("AddToStage.swf");                           var loader:Loader = new Loader();                           var signalTarget:IEventDispatcher = loader.contentLoaderInfo;                                                      loadedSignal = new NativeSignal(signalTarget, Event.COMPLETE, Event);                           loadedSignal.addOnce(onLoaded);                                                      progressSignal = new NativeSignal(signalTarget, ProgressEvent.PROGRESS, ProgressEvent);                           progressSignal.add(onProgress);                                                      faultSignal = new NativeSignal(signalTarget, IOErrorEvent.IO_ERROR, IOErrorEvent);                           faultSignal.addOnce(onFault);                                                      loader.load(request);                   }                    private function onFault(event:IOErrorEvent):void                   {                           trace("Something went wrong!");                   }                    private function onProgress(event:ProgressEvent):void                   {                           trace((event.bytesLoaded / event.bytesTotal) * 100);                   }                    private function onLoaded(event:Event):void                   {                           progressSignal.removeAll();                           addChild(event.target.content);                   }          }}

Processing MouseEvents

I will give another example to illustrate how to handle click events. The AddToStage class is returned. we add two private attributes.
Private var clicked: NativeSignal;
Private var box: Sprite;

Now draw a random image in the box and add it to the display list.

Box = new Sprite ();
Box. graphics. beginFill (0 xCCCCCC );
Box. graphics. drawRect (0, 0,100,100 );
Box. graphics. endFill ();
AddChild (box );

Add native clicksignal and callback function

Clicked = new NativeSignal (box, MouseEvent. CLICK, MouseEvent );
Clicked. add (onClicked );

Private function onClicked (event: MouseEvent): void
{
Trace ("clicked ");
}

Release the file, compile it into SWF, and run the loading SWF. When you click box, your console displays "clicked" each time you click it"

Now we not only use AS3 Signals to load external files, but also register a click listener and learn how to use the built-in event of ActionScript. This method is widely used.

Conclusion

In this article, you can learn how easy it is to use Robert Penner's AS3 Signal. We have learned three types of Signals and how to use them. I hope this article will benefit you. I also hope you like this communication method. Finally, I want to share some resources with you.

From: http://bbs.9ria.com/thread-66669-1-1.html

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.