Accessibility

Flex Documentation

Using mixins


Table of Contents

  1. Introduction to mixins
  2. Using mixins

To use a mixin, you instantiate the class to be mixed in and apply that class's methods to your custom class's prototype object. Then, you can call the mixed-in class's methods from instances of your custom class. The following steps describe this process for a custom class called GeekStoreDepartment.

To use a mixin:

  1. Import the necessary classes. This includes the mixin, plus the mx.core.Application class, as the following example shows:
    import mx.events.EventDispatcher;
    import mx.core.Application;
    

    Import the mx.core.Application class so that you can access the Flex application scope from within your custom class without having to type the entire package name. This is optional.

  2. Declare a static instance of the mixed in class, as the following example shows:
    static var evtDispatcher = mx.events.EventDispatcher;
    

    This explicitly instructs Flash to recognize your mixin before the static method call you make in a later step. You do this strictly for dependencies.

    In the Initialize() method of the custom class, instantiate the prototype object of the custom class, as the following example shows:

    var p = GeekStoreDepartment.prototype;
    
  3. Call the initialize() method of the mixed-in class, and pass it the prototype object, as the following example shows:
    EventDispatcher.initialize(p);
  4. (Optional) Return true.

    The entire Initialize() method appears as follows:

    static function Initialize() : Boolean {
      var p = GeekStoreDepartment.prototype;
      EventDispatcher.initialize(p);
    
      return true;
    }
    
  5. Call the custom class's Initialize() method and set a static variable to its return value. The return value is true for the first call to the custom class' Initialize() method.
    static var mixit : Boolean = GeekStoreDepartment.Initialize();
    

    As a result, Flex calls the Initialize() method only once. Because the variable is static, you only instantiate the object the first time the class is used and never have to instantiate it again for the life of the application. The result is less processing overhead and less memory usage.

  6. Declare the methods that you mixed in if you want to call the methods. For the EventDispatcher class, the relevant methods are addEventListener(), removeEventListener(), and dispatchEvent(). The following code adds these events:
    var addEventListener: Function;
    var removeEventListener: Function;
    var dispatchEvent: Function;
    
  7. To use the mixed-in methods, call them at any time as if they were defined on your class. The following example dispatches the modelChanged event when the custom class's setProperty() method is called:
    function setProperty(name:String, propertyValue, broadcastChange:Boolean) {
      // Normally, the following would be more complex than changing the
      // label value to "White".
      products[0].label="White";
    
      // Call dispatch event with the event object as an argument so it is passed appropriately
      dispatchEvent( {type: "modelChanged" } );
    }
    

The following custom TreeDataProvider class shows the result of these steps, and additional class logic that makes it a working example:

class GeekStoreDepartment implements mx.controls.treeclasses.TreeDataProvider {

  import mx.core.Application;
  import mx.events.EventDispatcher;

  // Force dependency before static call.
  static var evtDispatcher = mx.events.EventDispatcher;

  static function Initialize() : Boolean   {
    var p = GeekStoreDepartment.prototype;

    EventDispatcher.initialize(p);

    return true;
  }

  // Call the Initialize() method.
  static var mixit : Boolean = GeekStoreDepartment.Initialize();

  // Declare mixed-in methods.
  var dispatchEvent: Function;
  var addEventListener: Function;
  var removeEventListener: Function;

  // Simplified array
  var products: Array = [
        {label:"Red"},
        {label:"Green"},
        {label:"Blue"}
        ];

  // Custom DataProvider code would go here.

  // Minimal TreeDataProvider implementation.
  function hasChildNodes() : Boolean {return true;}

  function getChildNodes() : Array {return products;}

  function getProperty(name : String) {return products[name];}

  function setProperty(name : String, propertyValue, broadcastChange : Boolean) {
    products[0].label="White";
    dispatchEvent( {type: "modelChange" } );
  }

  function isTreeDataProvider() : Boolean {
    return true;
  }

  function indexOf(item: Object): Number {
    for (var i=0; i<products.length; i++) {
      if (products[i] == item) {
        return i;
      }
    }
  }

  // Stub out the rest of the TDP methods.
  function getData() : Object { }
  function setData(data : Object) {}
  function addTreeNode(arg,data) {}
  function addTreeNodeAt(index,arg,data) {}
  function removeTreeNodeAt(index) {}
  function removeTreeNode(){}
  function removeAll(){}
  function getTreeNodeAt(index : Number){}
}

The following MXML file instantiates the custom TreeDataProvider and calls the setProperty() method that triggers the mixed-in dispatchEvent() method call:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns:local="*">

  <local:GeekStoreDepartment id="myDP" />

  <mx:Tree id="myTree" dataProvider="{myDP}" />

  <mx:TextArea id="myTA" />

  <mx:Button click="myTA.text=myTree.dataProvider.setProperty('White');" label="Click Me" />

</mx:Application>