<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>FLEXible playground</title>
	<atom:link href="http://www.hrundik.ru/blog/ru/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hrundik.ru/blog</link>
	<description>(Hopefully) useful bits on flex, flash and related topics.</description>
	<lastBuildDate>Sun, 11 Apr 2010 06:43:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Бага во Flex SDK 4.0, связанная с обработчиками событий и состояниями</title>
		<link>http://www.hrundik.ru/blog/ru/2010/04/09/states-and-event-handler-related-bug-in-flex-sdk-4-0/</link>
		<comments>http://www.hrundik.ru/blog/ru/2010/04/09/states-and-event-handler-related-bug-in-flex-sdk-4-0/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 10:07:16 +0000</pubDate>
		<dc:creator>Hrundik</dc:creator>
				<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.hrundik.ru/blog/?p=42</guid>
		<description><![CDATA[Нашёл баг в релизной версии Flex SDK 4.0, которая приводит к утечке памяти. Если в вашей кастомной MXML-компоненте есть состояния и обработчик события, связанный с состоянием, то такая компонента навсегда останется в памяти.
Поэтому, не стоит использовать в промышленном коде обработчики событий с модификаторами состояния, как в примере:
&#60;s:Button label="Test" click.main="trace('click!')" /&#62;
Вместо этого можно использовать обычный обработчик события [...]]]></description>
			<content:encoded><![CDATA[<p>Нашёл баг в релизной версии Flex SDK 4.0, которая приводит к утечке памяти. Если в вашей кастомной MXML-компоненте есть состояния и обработчик события, связанный с состоянием, то такая компонента навсегда останется в памяти.</p>
<p>Поэтому, не стоит использовать в промышленном коде обработчики событий с модификаторами состояния, как в примере:</p>
<pre>&lt;s:Button label="Test" click.main="trace('click!')" /&gt;</pre>
<p>Вместо этого можно использовать обычный обработчик события с if-ом внутри:</p>
<pre>&lt;s:Button label="Test" click="if(currentState == 'main') trace('click!')" /&gt;</pre>
<p>Я порепортил баг Адобам, проголосуйте, может, быстрее поправят: <a href="https://bugs.adobe.com/jira/browse/SDK-26185" target="_self">https://bugs.adobe.com/jira/browse/SDK-26185</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hrundik.ru/blog/ru/2010/04/09/states-and-event-handler-related-bug-in-flex-sdk-4-0/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Monkey patches и Runtime Shared Libraries (RSLs)</title>
		<link>http://www.hrundik.ru/blog/ru/2009/10/05/monkey-patches-and-runtime-shared-libraries-rsls/</link>
		<comments>http://www.hrundik.ru/blog/ru/2009/10/05/monkey-patches-and-runtime-shared-libraries-rsls/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 00:08:13 +0000</pubDate>
		<dc:creator>Hrundik</dc:creator>
				<category><![CDATA[flex]]></category>
		<category><![CDATA[advanced]]></category>
		<category><![CDATA[Button]]></category>
		<category><![CDATA[monkey patching]]></category>
		<category><![CDATA[Preloader]]></category>
		<category><![CDATA[RSL]]></category>

		<guid isPermaLink="false">http://www.hrundik.ru/blog/?p=12</guid>
		<description><![CDATA[Monkey patching &#8211; это замена кусков flex framework своими собственными классами. Например, можно скопировать mx.core.UIComponent в папку src вашего проекта, изменить его, и после этого флекс будет использовать этот изменённый класс, вместо оригинального класса из библиотеки.
Вообще, такая практика считается злом, и я с этой точкой зрения согласен. Но иногда просто необходимо прибегнуть к monkey patching, [...]]]></description>
			<content:encoded><![CDATA[<p>Monkey patching &#8211; это замена кусков flex framework своими собственными классами. Например, можно скопировать mx.core.UIComponent в папку src вашего проекта, изменить его, и после этого флекс будет использовать этот изменённый класс, вместо оригинального класса из библиотеки.</p>
<p>Вообще, такая практика считается злом, и я с этой точкой зрения согласен. Но иногда просто необходимо прибегнуть к monkey patching, например, чтобы исправить баг фреймворка или как-то расширить его в случаях, когда наследование использовать невозможно.</p>
<p>И всё работает прекрасно до тех пор, пока вы не решите загружать фреймворк в виде RSL (Runtime Shared Library). После этого патчи работать перестанут.</p>
<p>Мы столкнулись именно с такой проблемой в нашем проект, <a href="http://www.talktoip.com">CommuniGate Pronto!</a>, и не смогли найти решение в интернете. Но в итоге нашли довольно уродливое, но при этом работающее решение.</p>
<h3>Немного теории</h3>
<p>Флэш-плеер обрабатывает загрузку реализаций классов следующим образов &#8211; в одном application domain может быть только одна реализация класса N. При этом, если в данном application domain уже есть реализация класс N, то ни при каких обстоятельствах в этом application domain она заменена не будет.</p>
<p>RSL (runtime shared library) &#8211; это просто .swf, в котором находятся определния и реализации каких-то классов. Framework RSL &#8211; это .swf с определениями и реализациями всех классов Flex Framework.</p>
<p>Флэш-приложение по своей природе разделено на кадры, как в мультике. Оно на самом деле и называлось до девятой версии плеера flash movie (мувик <img src='http://www.hrundik.ru/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). К каждому кадру могут быть привязаны какие-либо данные. В том числе определения и реализации классов.</p>
<p>Флэш-плеер загружает приложение по кадрам. Как только первый кадр полностью загружается, флэш-плеер начинает его проигрывать &#8211; привязывать реализации классов к опредениям, выполнять код, показывать картинку, проигрывать звук и так далее.</p>
<p>Компилятор flex (mxmlc) строит приложение, состоящее из двух кадров. В первый кадр мувика он записывает минимально возможное количество классов и ассетов для того, чтобы показать прелоадер, а во второй кадр записывает все классы, используемые в приложении. В том числе и фреймворк.</p>
<p>Дак вот &#8211; RSL подгружаются в первом кадре загрузчиком. И становятся определены в первом кадре. А monkey patched-реализации классов находятся во втором кадре, и поэтому не оверрайдят уже загруженные из RSL исходные реализации.</p>
<h3>Решение</h3>
<p>Возможным решением этой проблемы является использование кастомного прелоадера (разумеется, у каждого уважающего себя приложения должен быть кастомный прелоадер), в который можно добавить ссылку на патченные классы. Таким образом эти классы (и всех их зависимости) включаются в первый кадр приложения. Но такое решение сильно увеличивает размер загрузчика, поэтому я не думаю, что это решение может кого-то устроить. Подробно это решение описано в <a href="http://www.jamesward.com/blog/2009/03/10/flex-monkey-patching-and-framework-rsls/" target="_self">блоге James Ward</a>.</p>
<p>Более приемлемое решение становится очевидный, как только понимаешь, как работает flash-плеер.  В целом, нужно создать собственную RSL-библиотеку с патченными классами и сделать так, чтобы она загрузилась раньше RSL flex framework.</p>
<h4>Создание monkey-patched библиотеки</h4>
<p>Можно создать RSL с помощью встроенных фич флекс билдера. Создайте проект типа Flex Library, привяжите свой проект к этой библиотеке, и сделайте эту библиотеку загружаемой в виде RSL.  (project propertis -&gt; Flex Build Path -&gt; Library path -&gt; Link type под папкой библиотеки). Этим путём можно получить только довольно жирную библиотеки, поскольку флекс включит в неё бОльшую часть фреймворка. Но если в вашем случае был пропатчен небольшой класс с небольшим количеством зависимостей, то этот путь вас вполне может устроить. В моём случае библиотека получалась чересчур жирной, поэтому я решил пойти сложным путём.</p>
<p>Известно, что mxmlc позволяет контроллировать, какие классы нужно включать в .swf, а какие нет. Эта функциональность просто необходима для модулей и RSL, и ей можно управлять с помощью флагов компилятора externs, -external-library-path, -includes, -load-externs и некоторых других. Подробнее об этом можно прочитать в <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_14.html#157203">официальной документации</a>.</p>
<p>Идея в следующем &#8211; можно создать простое приложение с минимальным количеством зависимостей, заставить компилятор включить патченные классы в .swf, создать отчёт связывания (link report) и исключить из него все ненужные классы.</p>
<p>Будьте аккуратны &#8211; нельзя добавлять в это приложение зависимости от патченных классов, потому что это может всё сломать &#8211; в первом кадре flex framework ещё не загружен и зависимости не могут быть удовлетворены.</p>
<p>Код приложение должен выглядеть примерно так:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript3" style="font-family:monospace;"><span style="color: #9900cc; font-weight: bold;">package</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #0033ff; font-weight: bold;">import</span> <span style="color: #004993;">flash.display</span>.<span style="color: #004993;">Sprite</span>;
<span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #9900cc; font-weight: bold;">class</span> monkeylib extends <span style="color: #004993;">Sprite</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0033ff; font-weight: bold;">public</span> <span style="color: #339966; font-weight: bold;">function</span> monkeylib<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
          <span style="color: #0033ff; font-weight: bold;">super</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>После этого нужно это приложение собрать и создать отчёт связывания:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">&quot;c:\Program Files\Adobe\Flex Builder 3\sdks\3.2.0\bin\mxmlc&quot; -includes+=&quot;mx.controls.Button&quot; -link-report=monkey_report.xml monkeylib.as</pre></div></div>

<p>Далее нужно убрать патченные классы из отчёта и использовать его с -load-externs. Также нужно убрать главный класс приложения (monkeylib в нашем случае).</p>
<p>В качестве примера можно использовать класс <code>Button</code>.  Открываете monkey_report.xml, и с помощью Ctrl+F ищите строчку <code>:Button</code>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;C:\Users\Nikita\Documents\Flex Builder 3\monkeylib\src\mx\controls\Button.as&quot;</span> <span style="color: #000066;">mod</span>=<span style="color: #ff0000;">&quot;1254311407324&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;18581&quot;</span> <span style="color: #000066;">optimizedsize</span>=<span style="color: #ff0000;">&quot;15328&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;def</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.controls:Button&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.core:IButton&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.managers:IFocusManagerComponent&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.core:IDataRenderer&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.core:UIComponent&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.controls.listClasses:IDropInListItemRenderer&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.core:IFontContextComponent&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pre</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.controls.listClasses:IListItemRenderer&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dep</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;mx.styles:ISimpleStyleClient&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dep</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;flash.events:Event&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- ..... --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Весь этот блок нужно удалить, либо закомментировать.  Обратите внимание на идущие подряд теги <code>&lt;pre/&gt;</code>. По-моему, в данном случае &#8216;pre&#8217; обозначает &#8216;prerequisite&#8217;, то есть это список жизненно необходимых классов &#8211; родительского класса и интерефейсов, которые этот класс реализует. Все эти классы также нужно включить в библиотеку, иначе ничего не получится и во время загрузки библиотеки вы увидите ошибку VerifyError.</p>
<p>Помимо этих блоков <code>&lt;script/&gt;</code>, нужно удалить (или закомментировать) все теги <code>&lt;pre/&gt;</code>, которые ссылаются на класс, который вы хотите включить в библиотеку. Иначе он не будет в неё включен.</p>
<p>Таким образом, для класса <code>Button</code> нужно включить ещё классы <code>IButton, IFocusManagerComponent, IDataRenderer, IDropInListItemRenderer, IFontContextComponent, IListItemRenderer, UIComponent</code>.  Обратите внимание на <code>UIComponent</code>, наличие этого класса приводит к тому, что нужно включить и все его родительские классы:  <code>IPropertyChangeNotifier, ISimpleStyleClient, IStyleClient, IDeferredInstantiationUIComponent, IRepeaterClient, IValidatorListener, IInvalidating, ILayoutManagerClient, IUIComponent, FlexSprite, IFlexDisplayObject, IFlexModule, IConstraintClient, IToolTipManagerClient, IChildList, IAutomationObject, IStateClient, IUID</code>.<br />
Отчёт, который получился в итоге у меня, можно посмотреть здесь: <a href="http://www.hrundik.ru/blog/wp-content/uploads/2009/10/monkey_report.xml">monkey_report.xml</a></p>
<p>После этого нужно просто загрузить этот отчет с помощью <code>-load-externs</code> во время компиляции:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">&quot;c:\Program Files\Adobe\Flex Builder 3\sdks\3.2.0\bin\mxmlc&quot; -includes+=&quot;mx.controls.Button&quot; -load-externs=monkey_report.xml -link-report=libreport.xml monkeylib.as</pre></div></div>

<p>Очень полезно снова использовать флаг <code>-link-report</code> &#8211; можно сразу посмотреть, какие именно классы были включены в библиотеку.<br />
Если вы всё сделали правильно, то получится .swf-файл в 30kb (вместо 110kb, которые получаются без этих сложных процедур).</p>
<h4>Загружаем пропатченную библиотеку до framework RSL</h4>
<p>Хорошего пути решения этой проблемы я найти не смог &#8211; mxmlc всегда помещал RSL фреймворка раньше моей в списке загрузки. Поэтому снова пришлось прибегнуть к капельке черной магии манки патчинга. Я изменил класс <code>mx.preloaders.Preloader</code>; так, чтобы он помещал мою библиотеку в самое начало списка загрузки RSL. Тестовый проект можно сказат <a href="http://www.hrundik.ru/blog/wp-content/uploads/2009/10/LibTest.zip">тут</a>. Вот изменённые строки 179-184 класса <code>Preloader</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript3" style="font-family:monospace;"><span style="color: #009900;">// monkey patch</span>
<span style="color: #6699cc; font-weight: bold;">var</span> monkeyRSLNode<span style="color: #000000; font-weight: bold;">:</span>RSLItem = <span style="color: #0033ff; font-weight: bold;">new</span> RSLItem<span style="color: #000000;">&#40;</span><span style="color: #990000;">&quot;monkeylib.swf&quot;</span><span style="color: #000000;">&#41;</span>;
<span style="color: #0033ff; font-weight: bold;">if</span><span style="color: #000000;">&#40;</span>rslList.<span style="color: #004993;">length</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight:bold;">0</span><span style="color: #000000;">&#41;</span>
monkeyRSLNode.rootURL = RSLItem<span style="color: #000000;">&#40;</span>rslList<span style="color: #000000;">&#91;</span><span style="color: #000000; font-weight:bold;">0</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>.rootURL;
rslList.<span style="color: #004993;">unshift</span><span style="color: #000000;">&#40;</span>monkeyRSLNode<span style="color: #000000;">&#41;</span>;
<span style="color: #009900;">// ------------</span></pre></div></div>

<p>Вот и всё. Надеюсь, кому-нибудь эта информация пригодится. Если возникнут вопросы &#8211; задавайте в комментариях, постараюсь ответить.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hrundik.ru/blog/ru/2009/10/05/monkey-patches-and-runtime-shared-libraries-rsls/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Первый пост</title>
		<link>http://www.hrundik.ru/blog/ru/2009/10/05/first-post/</link>
		<comments>http://www.hrundik.ru/blog/ru/2009/10/05/first-post/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 00:07:41 +0000</pubDate>
		<dc:creator>Hrundik</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.hrundik.ru/blog/?p=32</guid>
		<description><![CDATA[Привет!
Добро пожаловать в мой блог. Меня зовут Никита Петров, я flash/felx &#8211; разработчик.
Попытаюсь писать только о неочевидных проблемах во flex и flash &#8211; решения очевидных можно легко найти в интернете и документации.
А ещё я знаю английский, и хотя мои познания языка далеки от идеального, я буду писать на двух языках &#8211; русском и английском. Буду [...]]]></description>
			<content:encoded><![CDATA[<p>Привет!<br />
Добро пожаловать в мой блог. Меня зовут Никита Петров, я flash/felx &#8211; разработчик.</p>
<p>Попытаюсь писать только о неочевидных проблемах во flex и flash &#8211; решения очевидных можно легко найти в интернете и документации.</p>
<p>А ещё я знаю английский, и хотя мои познания языка далеки от идеального, я буду писать на двух языках &#8211; русском и английском. Буду стараться публиковать записи синхронно.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hrundik.ru/blog/ru/2009/10/05/first-post/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
