読者です 読者をやめる 読者になる 読者になる

パフォーマンスを要求される場面でitemRendererFunctionを使ってはいけない

AIR

FlexといえばItemRendererは避けてとれないかと思います。
で、このItemRendererで、違うオブジェクトが混ざったArrayCollectionでそのオブジェクトにあわせてItemRendererを選んで表示したくなったりすることがあるかと思います。
Flex3まででこういう場合どうするのかというと、例えばStateを使ってどうにかしてみるとか、全部入りにしちゃって泥臭くset dataでがんばったり、まあいくつか方法はありますが、エレガントに解決しようとするのは中々大変です。


で、Flex4以降のSparkコンポーネントベースのItemRendererでは、そういった場合にitemrendererFunctionというのが使えるようになりました。
こんな感じになります

	<fx:Script>
		<![CDATA[
//.....................................................

			private function selectItemRenderer(item:Object):ClassFactory {
				var iFactory:ClassFactory;
				if(item is TwitterObject){
					iFactory = new ClassFactory(TwitterRenderer);
				}else if(item is FacebookObject){
					iFactory = new ClassFactory(FacebookRenderer);
				}
				return iFactory;
			}
    ]]>
</Fx:Script>
//...............................
<s:List id="snsMixList"
				width="100%"
				height="100%"
				dataProvider="{snsMixCollection}"
				itemRendererFunction="selectItemRenderer"
				/>
//....................................
			

オブジェクトにあわせてItemRendererを振り分けるコードがすっきり書けてめでたしめでたし・・と、行きたいのですが、実はこのitemRendererFunctionには大きな問題があります。どういう問題かというと、コレです。
http://help.adobe.com/ja_JP/flex/using/WS64909091-7042-4fb8-A243-8FD4E2990264.html

If you define an itemRendererFunction to determine the item renderer for each data item, Flex will not reuse item renderers. The itemRendererFunction must examine each data item and create the item renderers as necessary for the specific data item type. While Flex does not reuse item renderers, it only creates enough item renderers for the currently visible data items.

itemRendererFunction使うと通常のItemRendererのようにはreuseされないと。ItemRendererのreuseして節約というメリットががががが。
というわけで、ArrayCollectionやArrayListに大量にデータが入っているようなケースではこのitemRendererFunctionを使うと、パフォーマンス的にちょっとまずいことになる場合があります。というか、SOICHA開発時初期に実際に使っていて滅茶苦茶遅くなりました。どこで使用していたかはまあ想像つくかと思います。Twitterクライアントですし。


じゃあパフォーマンスを要求されるような場面でこういったことをしたい場合はどうするのかということですが、itemRendererFunctionを説明しといてあれですが、今までのようにがんばるしかないのではないかなと思います。
ArrayCollectionへのデータ追加のタイミングでitemRendererを決定するとか、Stateを使ってみたり、set dataでがんばったり。
あるいはItemRendererを継承、またはdatarendererをimplimentしたクラスを作成して内部でうまいこと処理する、といった所かと。
究極的にはItemRenderer使わないでオレオレItemRenderer機構を作るのが一番の解決策、な気がしますw