Использование Flex вместе с haXe

Это черновая версия статьи о том, как совместить Flex-фреймворк и haXe. Здесь описан один из способов разработки Flex-приложения для 9-го флэш-плеера с использованием кода на haXe.

Статья требует базовых знаний о Flex, haXe, AS3 и MXML. Решение, описанное в статье, разрабатывалось и отлаживалось на релиз-версии 9-го флэш-плеера. На более ранних бета-версиях оно может не работать.

В примере используется минимальный MXML-файл и AS3 класс для инициализации Flex-приложения и загрузки внешнего swf-файла, содержащего классы haXe в виде байт-кода флэш-плеера.

Минимальное Flex-приложение содержит довольно много кода. Его можно посмотреть, если при компиляции указать опцию "compiler.keep-generated-actionscript". При этом компилятор mxmlc сохранит промежуточный AS-код, сгенерированный из MXML. Там вы обнаружите массу кода, выполняющего загрузку и инициализацию Flex-приложения.

Код во Flex-приложении размещен в двух отдельных кадрах фильма. Первый кадр содержит SystemManager и классы загрузчика, инициирующие процесс загрузки, второй кадр содержит весь остальной код приложения. Это позволяет быстро загрузить и выполнить код первого кадра и отслеживать загрузку остального кода приложения.

В идеале, нужно было бы скомпилировать минимальное Flex-приложение компилятором mxmlc, а затем внедрить наши haXe классы во второй кадр сгенерированного swf-файла. Однако я не уверен, что это получится, поэтому пошел другим путем -- Flex-приложение динамически загружает swf-файл, содержащий haXe классы, затем AS3 классы создают и вызывают haXe классы и наоборот.

Минимальное Flex-приложение

Создайте новый файл со следующим MXML кодом:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:base="*">
   <base:ApplicationCanvas/>
</mx:Application>

Сохрание его как haxeflex.mxml. Это самый минимальный MXML файл который просто создает экземпляр класса ApplicationCanvas на сцене. Мы определим класс ApplicationCanvas в отдельном AS3 файле. Создайте новый файлы с именем ApplicationCanvas.as и добавьте в него код:

package {

   import flash.display.*;
   import flash.net.URLRequest;
   import flash.events.Event;
   import mx.core.*;
   import mx.controls.*;
   import mx.containers.*;
   import flash.system.ApplicationDomain;
   import flash.system.LoaderContext;


   public class ApplicationCanvas extends Canvas {

      public function ApplicationCanvas() {

         // load haxeApplication swf
         var ldr:Loader = new Loader();
         var swfUrl:String = "haxeApplication.swf";
         var req:URLRequest = new URLRequest(swfUrl);
         var ldrContext:LoaderContext = 
            new LoaderContext(false, ApplicationDomain.currentDomain);
         ldr.load(req, ldrContext);
         ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded);
      
         // Nested callback function for SWF loading
         function swfLoaded(e:Event):void {
            // TODO - load an instance of the HaxeApplication class
         }
      }
   }
}

Наконец, скомпилируйте приложение компилятором mxmlc:
"mxmlc haxeflex.mxml"

Будет сгенерирован файл haxeflex.swf.

Создаем haXe-библиотеку

Теперь создадим базовый swf-файл, содержащий пустой haXe класс. Мы добавим его позже. Создайте новый файл с именем HaxeApplication.hx:

class HaxeApplication {

   // contructor
   public function new() { }

}

Скомпилируйте haXe приложение:
"haxe -swf-version 9 -swf haxeApplication.swf HaxeApplication"

Будет сгенерирован swf-файл с именем haxeApplication.swf содержащий пустой класс.

Загружаем haXe-библиотеку

Система безопасности флэш-плеера по умолчанию не разрешает загрузку внешнего фильма в локальной файловой системе. Я уверен, что есть способ обойти это ограничение, но я избежал этого, просто используя локальный веб-сервер (Apache). Так что теперь нужно скопировать swf-файлы в document root веб-сервера и загрузить их с помощью браузера:

http://localhost/haxeflex.swf

Если все в порядке (не возникло никаких исключений), то вы увидите пустой серой фон Flex-приложения. Это значит, что Flex-приложение успешно загрузило swf-файл с haXe классом.

Создаем экземпляры haXe классов из AS3

Экземпляр класса HaxeApplication создается в два шага: загрузка определения класса и использование оператора new с этим определением. Замените тело функции swfLoaded в ApplicationCanvas.as следующим кодом:

// Get the definition of the HaxeApplication class from the application domain
var haxeApplicationDef:Class = 
   ApplicationDomain.currentDomain.getDefinition("HaxeApplication") as Class;

// Use the new operator to create a new instance of the class
var haxeApplication:Object = new haxeApplicationDef();

Снова скомпилируйте haxeflex.mxml и откройте приложение в браузере. Вы не увидите никаких изменений, но и никаких ошибок не возникнет. Значит экземпляр класса успешно создан.

Создаем и вызываем AS3 классы из haXe

Последний шаг в нашем примере -- создать новый компонент Flex button в классе HaxeApplication и вернуть его экземпляру AS3 canvas, который, в свою очередь добавит его как child.

Чтобы создать экземпляр не-haXe класса, нужно предоставить компилятору описание интерфейса этого класса. Для этого мы создадим описание внешнего класса -- каркас, описывающий только public методы и свойства. Ключевое слово extern скажет компилятору, что этот класс будет скомпилирован отдельно.

Чтобы компилятор имел описания всех классов пакета mx, нужно установить библиотеку Flex haXe, запустив команду:
haxelib install flex

Теперь можно просто добавить"-lib flex" к параметрам компиляции и собрать проект компилятором haXe.

Компилятор будет знать о Flex-классе Button так что мы можем подключить его конструкцией import, создать экземпляр и обращаться к его свойствам, как и с обычным haXe классом. Добавьте такой import и новый метод в HaxeApplication.hx и скомпилируйте его:

import mx.controls.Button;

//-- SNIP --

public function getButton():Button {
   var button:Button = new Button();
   button.label = "Hello Flex world from haXe";
   return button;
}

Теперь добавьте в ApplicationCanvas.as вызов метода getButton:

// fetch the button instance - call to a haXe class
var button: Button = haxeApplication.getButton();

// add the button to the canvas
addChild(button);

Скомпилируйте MXML приложение и загрузите haxetest.swf в браузере. Вы увидите серый фон и кнопку с надписью Hello Flex world from haXe.

Наше AS3 Flex-приложение создало экземпляр haXe класса HaxeApplication, вызвало его метод, который, в свою очередь, создал и вернул экземпляр AS3 класса. Теперь AS3 и haXe классы могут взаимодействовать в обоих направлениях.

version #4025, modified 2008-08-19 21:54:11 by yzh44yzh