Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > incvizitor

Рейтинг: 4.75. Голосов: 4.

Метатеги времени исполнения.

Запись от incvizitor размещена 15.12.2012 в 21:19
Обновил(-а) incvizitor 23.12.2012 в 23:10

Очень часто, общаясь с коллегам, я замечаю, что многие весьма поверхностно знакомы с возможностями использования метатегов в ActionScript 3.0. Конечно большинству эта тема будет уже не интересна, однако многие живут годами, не зная о такой мощной фиче AS3 как метатеги. Ну или не зная всех возможностей . Именно для этих людей и предназначается данная статья.

Код изложенный в этой статье максимально прост, и написан как можно более кратко, что бы объяснить основную концепцию. Но для практических задач он неприемлем, так как в нем не учтены многие ньюансы. В следующей статье, мы придадим ему более полный вид.

Итак начнем:

Для начала определим три вида метатегов:

Метатеги времени компиляции:

Это по сути инструкции компилятору, чаще всего они указывают, что код необходимо преобразовать. Самый известный пример - [Bindable]. Подробнее об этом метатеге можно почитать тут: http://blog.diestro.ru/binding-v-actionscript-1/

Метатеги - инструкции для IDE:

Данные метатеги никак не влияют на приложение. Они исключительно помогают кодогенерации и другим фичам IDE, так же некоторые из них (например [Deprecated]) вызавут ворнинг во время компиляции, при использовании свойств отмеченных ими. Самые известные:
[Exclude] - удаляет свойство из MXML автокомплита.
[Inspectable] - позвотяет описать возможные значения которые принимает сеттер. Крайне удобен при работе с MXML.

Метатеги времени исполнения:

Так же существует возможноть пометить нейкое свойство, метод или весь класс метатегом, что бы использовать метатег как инструкцию для каких либо действий. Существует много фреймворков, позваляюших осуществлять доступ к метатегам, однако мы расмотрим этот вопрос, так сказать, на низком уровне.

Давайте расмотрим следующий пример:

Код AS3:
package view {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFormat;
 
	/**
	 * ...
	 * @author vaukalak
	 */
	public class TimerView extends Sprite {
		private var _textField:TextField;
 
 
		public function TimerView() {
			_textField = new TextField();
			_textField.defaultTextFormat = new TextFormat(null, 30);
			addChild(_textField);
		}
 
		[EnterFrame]
		public function update(event:Event):void {
			_textField.text = String(uint(_textField.text) + 1);
		}
 
	}
 
}
Вы наверное догадались, что метод update будет вызываться на каждое событие enterFrame. Но для того, что бы это так работало, нужно немного потрудится .

Во первых: нам нужно добавить в доп. опции компилятора следующую строчку:

Код:
-keep-as3-metadata+=EnterFrame
Это делается для того, что бы компилятор не вырезал метатег, и мы могли его исользовать.

Во втрорых: нам нужен механизм, который проанализирует наш класс и увидев в его описании метатег EnterFrame, сделает то что нам нужно.

Для того, что бы получить описание класса в формате XML, нужно написать следующий код:

Код AS3:
var description:XML = flash.utils.describeType(myObject);
Вот как выглядит описание нашего класса:

Код:
<type name="view::TimerView" base="flash.display::Sprite" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="flash.display::Sprite"/>
  <extendsClass type="flash.display::DisplayObjectContainer"/>
  <extendsClass type="flash.display::InteractiveObject"/>
  <extendsClass type="flash.display::DisplayObject"/>
  <extendsClass type="flash.events::EventDispatcher"/>
  <extendsClass type="Object"/>
  <implementsInterface type="flash.events::IEventDispatcher"/>
  <implementsInterface type="flash.display::IBitmapDrawable"/>
  <accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scaleZ" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="rotationX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="rotationY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
  <accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
  <accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
  <accessor name="tabChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
  <accessor name="rotationZ" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mouseChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
  <accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
  <accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
  <accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
  <accessor name="z" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
  <accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="soundTransform" access="readwrite" type="flash.media::SoundTransform" declaredBy="flash.display::Sprite"/>
  <accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
  <accessor name="hitArea" access="readwrite" type="flash.display::Sprite" declaredBy="flash.display::Sprite"/>
  <accessor name="dropTarget" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::Sprite"/>
  <accessor name="buttonMode" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
  <accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
  <accessor name="numChildren" access="readonly" type="int" declaredBy="flash.display::DisplayObjectContainer"/>
  <accessor name="textSnapshot" access="readonly" type="flash.text::TextSnapshot" declaredBy="flash.display::DisplayObjectContainer"/>
  <accessor name="useHandCursor" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
  <accessor name="blendShader" access="writeonly" type="flash.display::Shader" declaredBy="flash.display::DisplayObject"/>
  <accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
    <metadata name="Inspectable">
      <arg key="environment" value="none"/>
    </metadata>
  </accessor>
  <accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="graphics" access="readonly" type="flash.display::Graphics" declaredBy="flash.display::Sprite"/>
  <accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
  <accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
  <accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
    <parameter index="4" type="int" optional="true"/>
    <parameter index="5" type="Boolean" optional="true"/>
  </method>
  <method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="flash.events::Event" optional="false"/>
  </method>
  <method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <method name="addChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <method name="removeChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="removeChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="int" optional="false"/>
  </method>
  <method name="getChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="int">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
  <method name="setChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <method name="getChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="int" optional="false"/>
  </method>
  <method name="swapChildrenAt" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="int" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <method name="swapChildren" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="globalToLocal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="startTouchDrag" declaredBy="flash.display::Sprite" returnType="void">
    <parameter index="1" type="int" optional="false"/>
    <parameter index="2" type="Boolean" optional="true"/>
    <parameter index="3" type="flash.geom::Rectangle" optional="true"/>
  </method>
  <method name="getBounds" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="getObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Array">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="getRect" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="localToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="areInaccessibleObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="stopTouchDrag" declaredBy="flash.display::Sprite" returnType="void">
    <parameter index="1" type="int" optional="false"/>
  </method>
  <method name="hitTestObject" declaredBy="flash.display::DisplayObject" returnType="Boolean">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="hitTestPoint" declaredBy="flash.display::DisplayObject" returnType="Boolean">
    <parameter index="1" type="Number" optional="false"/>
    <parameter index="2" type="Number" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <method name="getChildByName" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <method name="startDrag" declaredBy="flash.display::Sprite" returnType="void">
    <parameter index="1" type="Boolean" optional="true"/>
    <parameter index="2" type="flash.geom::Rectangle" optional="true"/>
  </method>
  <method name="globalToLocal3D" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Vector3D">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="stopDrag" declaredBy="flash.display::Sprite" returnType="void"/>
  <method name="local3DToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
    <parameter index="1" type="flash.geom::Vector3D" optional="false"/>
  </method>
  <method name="update" declaredBy="view::TimerView" returnType="void">
    <parameter index="1" type="flash.events::Event" optional="false"/>
    <metadata name="EnterFrame"/>
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="469"/>
    </metadata>
  </method>
  <method name="contains" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="addChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <metadata name="__go_to_ctor_definition_help">
    <arg key="pos" value="290"/>
  </metadata>
  <metadata name="__go_to_definition_help">
    <arg key="pos" value="199"/>
  </metadata>
</type>
Много текста, но нас интересует вот этот участок:

Код:
  <method name="update" declaredBy="view::TimerView" returnType="void">
    <parameter index="1" type="flash.events::Event" optional="false"/>
    <metadata name="EnterFrame"/>
    <metadata name="__go_to_definition_help">
      <arg key="pos" value="469"/>
    </metadata>
  </method>
Как видно, среди метаданных метода есть EnterFrame. Все что нам нужно, это выдрать имя метода из описания. Сделать это можно с помощью E4X:

Код AS3:
describeType(myObject).method.(valueOf().metadata.(@name == "EnterFrame").length()).@name
По сути, мы получаем описание объекта, пробегаем по методам, выбираем те, что помечены метатегом EnterFrame, и забираем их имя.

Это была самая сложная часть

Вот небольшой пример нашего менеджера:

Код AS3:
package reflection {
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.utils.describeType;
	import flash.utils.Dictionary;
 
	/**
	 * ...
	 * @author vaukalak
	 */
	public class EnterFrameHelper {
 
		private const _linker:Dictionary = new Dictionary(true);
 
		public static const cache:Dictionary = new Dictionary();
 
		public function startOn(container:DisplayObjectContainer):void {
			//будем проверять все объекты, которые добавляются в container, или в его детей.
			container.addEventListener(Event.ADDED, _onChildAdded, true); 
		}
 
		private function _onChildAdded(event:Event):void {
 
			var targetDO:DisplayObject = event.target as DisplayObject;
			//Массив методов помеченных EnterFrame
			var handlers:Vector.<Function> = new Vector.<Function>(); 
 
			//находим тип нашего объекта и кешируем его описание. 
			//метод describeType весьма прожерливый, так что кешировать его обязательно.
			var objectClass:Class = Object(event.target).constructor;
			cache[objectClass] ||= describeType(event.target);
			//находим все методы, помеченные метатегом EnterFrame 
			//и пихаем их в массив обработчиков
			cache[objectClass].method.(valueOf().metadata.(@name == "EnterFrame").length()).(handlers.push(targetDO[@name]));
 
			if (handlers.length) {
				//если обработчики есть, то как только объект добавиться на сцену, 
				//сразу подпишем его на ентерфрейм
				targetDO.addEventListener(Event.ADDED_TO_STAGE, _onTargetAddedToStage, false, 0, true);
				targetDO.addEventListener(Event.REMOVED_FROM_STAGE, _onTargetRemovedFromStage, false, 0, true);
				_linker[targetDO] = handlers;
			}
 
		}
 
		private function _onTargetRemovedFromStage(event:Event):void {
			(event.target as DisplayObject).removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
 
		private function _onTargetAddedToStage(event:Event):void {
			(event.target as DisplayObject).addEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
 
		private function _onEnterFrame(event:Event):void {
			for each(var handler:Function in _linker[event.target]) {
				handler(event);
			}
		}
 
	}
 
}
И документ класс:
Код AS3:
package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.describeType;
	import reflection.EnterFrameHelper;
	import view.TimerView;
	import view.TimerViewWithoutReflection;
 
	/**
	 * ...
	 * @author vaukalak
	 */
	public class Main extends Sprite {
 
		private var _enterFrameHelper:EnterFrameHelper;
 
		public function Main():void {
			_enterFrameHelper = new EnterFrameHelper();
			_enterFrameHelper.startOn(stage); //будем описывать все, что попадет на сцену.
			addChild(new TimerView());
		}
 
	}
 
}
А вот как выглядел бы класс TimerView без использования метатегов:

Код AS3:
package view {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFormat;
	/**
	 * ...
	 * @author vaukalak
	 */
	public class TimerViewWithoutReflection extends Sprite{
 
		private var _textField:TextField;
 
		public function TimerViewWithoutReflection() {
			_textField = new TextField();
			_textField.defaultTextFormat = new TextFormat(null, 30);
			addChild(_textField);
			addEventListener(Event.ADDED_TO_STAGE, _onAddedToStage, false, 0, true);
			addEventListener(Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false, 0, true);
		}
 
		private function _onRemovedFromStage(e:Event):void {
			removeEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
 
		private function _onAddedToStage(e:Event):void {
			addEventListener(Event.ENTER_FRAME, _onEnterFrame);
		}
 
		private function _onEnterFrame(e:Event):void {
			_textField.text = String(uint(_textField.text) + 1);
		}
 
	}
 
}
По моему разница в читаемости очевидна. К тому же мы избавились от самой нудной части написания нашего класса.
Всего комментариев 21

Комментарии

Старый 16.12.2012 18:10 GBee вне форума
GBee
 
Аватар для GBee
Оу, в примере столько мороки, что преимущества совсем не видать. Но в целом интересно.
Старый 16.12.2012 19:16 etc вне форума
etc
 
Аватар для etc
Тема хорошая, только применяется не там, где надо.
Старый 16.12.2012 20:22 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
Денис, я, надеюсь, это будет во второй части
Старый 16.12.2012 21:08 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
GBee, ну, а как бы менеджер написать нужно один раз, а метатег применить - много. Каждый раз, когда выделяешь общий механизм, это вряд ли отобъется на одном использовании.

etc, да, сдесь хотелось самый минимальный и понятный пример. И хотелось не Inject, а что то, чего нету. Но вообще в небольших проектах вешал таким образом ентерфрейм. Проблем не было, код читать было проще, вероятность ошибки уменшалась, так как все автоматизировано. Это тривиальная вещь, почему бы её не автоматизировать?
Старый 16.12.2012 21:57 GBee вне форума
GBee
 
Аватар для GBee
Цитата:
GBee, ну, а как бы менеджер написать нужно один раз, а метатег применить - много. Каждый раз, когда выделяешь общий механизм, это вряд ли отобъется на одном использовании.
Да это понятно, только прицепить интерфейс на класс проще и читабельнее в данном случае (и чувствуется, что быстрее).
Старый 16.12.2012 22:06 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
прицепить можно, а что конкретно с ним делать?
Старый 16.12.2012 22:47 GBee вне форума
GBee
 
Аватар для GBee
Код AS3:
var targetDO:DisplayObject = event.target as DisplayObject;
if (targetDO is IEnterFrameable) {
	targetDO.addEventListener(Event.ADDED_TO_STAGE, _onTargetAddedToStage, false, 0, true);
	targetDO.addEventListener(Event.REMOVED_FROM_STAGE, _onTargetRemovedFromStage, false, 0, true);
	_linker[targetDO] = targetDO.handler; //handler - реализует IEnterFrameable
}
И то уже избыточно, можно сразу хендлер подписывать.
Старый 16.12.2012 23:13 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
1 - а если обработчиков несколько?
2 - ну Вы конечно о конкретном примере пишете. Но я бы предложил продумать пару шагов вперед. Допустим будем еще exitFrame слушать. У Вас будет интерфейс IExitFrameable с методом handler. Получится что на оба события будет подписан один и тот же метод.
3 - И вообще странновато будет implements IEnterFrameable, IExitFrameable, ...
Старый 16.12.2012 23:40 GBee вне форума
GBee
 
Аватар для GBee
1 - а есть реальный смысл, если не разные фазы ловить (кстати, как у вас с этим)? Можно вызывать разные методы в хендлере.
2 - Да handler я от балды написал. Методы по-разному будут называться. Ну да получится свитч/хеш. А у вас как будет? :о)
3 - Нормально будет. Закомментил - отвалился. И не надо класс шерстить - есть ли тут метатег.

Я говорю, тема довольно интересная, но пример реально слабый.
Старый 17.12.2012 03:33 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
1 - никогда не указывал фазы для ентерфрейма. Можно в обработчике 2 метода сделать, но если 2 метода между собой не сильно связаны, то можно и 2 обработчика. По производительности это никак не ударит. Но в общем спорить на эту тему особо не собираюсь.
2,3 - будет хеш. Но это не суть. Имплементить кучу интерфейсов, просто для того, что бы кто то мог с нами, что то сделать - это реально жесть. Если Вы заюзаете действительно полезный интерфес, то не увидите его среди прочего мусора. Я не верю, что Вы так пишите.

Пример хотел написать, как можно проще. А проще, кажется, невозможно. Просто сдесь только концепция, механизм, примеры будут в следующей статье. Хотя, почти все, от кого я получил отзыв, сказали, что лучше было писать их тут.

В любом случае, спасибо за Ваш пост, перед публикацией второй статьи (там будут более интересные примеры), обязательно обращусь к Вам за отзывом.
Старый 17.12.2012 12:47 GBee вне форума
GBee
 
Аватар для GBee
Да я не про ентерфрейм, вообще.
Цитата:
Я не верю, что Вы так пишите.
Да как то не было задачи менеджерить ентерфрейм для кучи объектов. А для мышиных событий можно и в контейнер подписаться.

А продолжения жду.
Старый 17.12.2012 16:48 etc вне форума
etc
 
Аватар для etc
Этот пример понятен, но он также нарочито показывает лень разработчика.
Старый 17.12.2012 19:12 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Отлично! Интересно, спасибо :3
Старый 23.12.2012 21:35 dimarik вне форума
dimarik
 
Аватар для dimarik
describeType очень ресурсоемкая операция. Поиск по XML дереву — тоже. Если будете сохранять хотя бы малую часть строки из XML, то весь XML останется в памяти. describeType всегда возвратит новый объект XML. Памяти в таком случае будет отжираться немеряно. Ну это немного поборено кэшированием.

Код AS3:
//будем проверять все объекты, которые добавляются на сцену. 
container.addEventListener(Event.ADDED, _onChildAdded, true);
Комментарий не соответствует действительности. Исправьте на "будем проверять все объекты, которые добавляются в container". При этом container не обязан быть в дисплей листе.

Цитата:
Тема хорошая, только применяется не там, где надо.
Денис, раскрой мысль, пожалуйста )
Старый 23.12.2012 23:25 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
dimarik, спасибо. Исправил, немного видоизменив.
Что на счет кеширования - да, оно должно быть централизированным. То есть должен быть нейкий MetadataHelper, который кеширует описание всех дескрипнутых классов. А уже обработчики конкретного метотега должны регистрериваться в систему, и пользоваться дескрипшеном из MetadataHelper. Но в этой статье я хотел сказать 2 вещи:
1 - есть такая функция flash.utils.describeType.
2 - через нее можно получить получить описание класса, конкретного объекта в формате XML. В том числе метатеги.

В следующей статье я распишу этот процесс более детально .
Старый 26.12.2012 23:17 etc вне форума
etc
 
Аватар для etc
А чего раскрывать тему, тут в примере типа показываем, что нам лень отписываться (но не лень подписываться). Честное слово, пример с десериализацией чего-нибудь и тот интересней.
Старый 27.12.2012 20:38 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
etc, ну вообще, мы еще отвязываемся и от прослушки добавления/удаления со сцены. Лично мне читать проще если локальные хендлеры в метатегах, если это возможно.

Лично мне, пример с десериализацией был бы очень интересен. И еще, когда Вы дескриптаете модельки, по добавлении в базу? Или это не в модельках?
Старый 04.01.2013 11:36 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Тема довольно интересная.
В приложении с сотнями классов пожалуй кешировать всю хмл избыточно. Возможно лучше так
Код AS1/AS2:
var objectClass:Class = Object(event.target).constructor;
var handlers:Vector.<Function> = cache[objectClass];
if (!handlers) {
    cache[objectClass] = handlers = new Vector.<Function>(); 
    describeType(event.target).method.(valueOf().metadata.(@name == "EnterFrame").length()).(handlers.push(targetDO[@name]));
}
Старый 05.01.2013 19:13 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
f.g.programmer, ну на проекте с примерно 1000 классов проблем не давало а вот если некоторые классы нужно описать 100 раз - то проблемы будут. В Вашем примере, вы кешируете конкретные методы, конкретного объекта.
Старый 05.01.2013 20:08 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Цитата:
f.g.programmer, ну на проекте с примерно 1000 классов проблем не давало а вот если некоторые классы нужно описать 100 раз - то проблемы будут. В Вашем примере, вы кешируете конкретные методы, конкретного объекта.
Да, пример неправильный, поспешил скопипастить, но суть, думаю, понятна

Насчет тысячи классов, getSize(describeType(new Sprite()))) показывает около 40кб, т.е. потенциальная потеря 40мб. Для современных компьютеров потеря, возможно, незначительная, но не неообходимая
Старый 05.01.2013 20:25 incvizitor вне форума
incvizitor
 
Аватар для incvizitor
Суть то понятна, однако проблему не решает. describeType нужно будет все равно вызывать каждый раз. То есть если нам нужно продескрайпить одновременно 100 (а ведь может быть значительно больше) моделек, то лаг будет заметен. Можно конечно попробовать продескрайпить их в "одном потоке", то есть закешировать временно XML, но что то подсказывает, что универсальной реализации не получится.. Мне кажется, было бы целесообразно кешировать нейкий модуль, а при выгрузке - удалять его кешь. Это будет, скорее всего, менее сложный и более универсальный вариант.

П.С. и из 1000 классов далеко не все въюшки
 
Последние записи от incvizitor

 


Часовой пояс GMT +4, время: 23:24.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.