2013/10/24

Flex:: カスタムItemRendererの画像がチラつくのを防ぐ方法

Flex 4.10:: ItemRendererをカスタムで作って、その中にアイコン等の画像を置くと、リストやドロップダウンリストでスクロールするとき、そのアイコンや画像がチラついてしまいます。

原因はカスタムで作ったItemRendererに画像を置くと、リストをスクロールする度に画像を取得し直すためです。

解決方法として、画像イメージをキャッシュする方法を使います。
Flexには「ContentCache」クラスという便利な機能があり、このクラスを使うと比較的簡単に画像キャッシュ機能を実装できます。

■手順
  1. ImageCache用のクラスをSingletonで作成します。(Singletonで作成する理由は、ItemRenderer内で画像を使う際に、同じImageCacheクラスのインスタンスにアクセスする必要があるからです。)
  2. カスタムのItemRendererから画像ソースを設定する直前のところで、contentLoaderにキャッシュをセットします。
■結果(画像)


■ソースコード(メインMXML)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" minWidth="955" minHeight="600"
      xmlns:myclasses="myclasses.*">
 
 <s:HGroup gap="20">
  <s:List width="180" height="300"
    itemRenderer="views.itemrenderers.CustomItemRenderer">
   <s:dataProvider>
    <s:ArrayList>
     <myclasses:TestClass iconPath="assets/images/icon_1.png" itemName="テストアイテム1" itemDesc="テストアイテム1についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_2.png" itemName="テストアイテム2" itemDesc="テストアイテム2についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_3.png" itemName="テストアイテム3" itemDesc="テストアイテム3についての説明"/>
  <!-- 省略 -->
     <myclasses:TestClass iconPath="assets/images/icon_1.png" itemName="テストアイテム1" itemDesc="テストアイテム1についての説明。"/>
     <myclasses:TestClass iconPath="assets/images/icon_2.png" itemName="テストアイテム2" itemDesc="テストアイテム2についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_3.png" itemName="テストアイテム3" itemDesc="テストアイテム3についての説明"/>
    </s:ArrayList>
   </s:dataProvider>
  </s:List>
  <s:List width="180" height="300"
    itemRenderer="views.itemrenderers.CustomCacheItemRenderer">
   <s:dataProvider>
    <s:ArrayList>
     <myclasses:TestClass iconPath="assets/images/icon_1.png" itemName="テストアイテム1" itemDesc="テストアイテム1についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_2.png" itemName="テストアイテム2" itemDesc="テストアイテム2についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_3.png" itemName="テストアイテム3" itemDesc="テストアイテム3についての説明"/>
  <!-- 省略 -->
     <myclasses:TestClass iconPath="assets/images/icon_1.png" itemName="テストアイテム1" itemDesc="テストアイテム1についての説明。"/>
     <myclasses:TestClass iconPath="assets/images/icon_2.png" itemName="テストアイテム2" itemDesc="テストアイテム2についての説明"/>
     <myclasses:TestClass iconPath="assets/images/icon_3.png" itemName="テストアイテム3" itemDesc="テストアイテム3についての説明"/>
    </s:ArrayList>
   </s:dataProvider>
  </s:List>
 </s:HGroup>
</s:Application>

■ソースコード(カスタムItemRenderer)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    autoDrawBackground="true">
 <fx:Script>
  <![CDATA[
   import myclasses.ImageCache;
   
   override public function set data(value:Object):void
   {
    super.data = value;
    if (value == null)
     return;
    
    if ( !img.contentLoader ) 
    {
     img.contentLoader = ImageCache.getInstance().cache;
    }
    
    img.source = value.iconPath;
   }
  ]]>
 </fx:Script>
 
 <s:HGroup verticalAlign="middle">
  <s:Image id="img" width="24" height="24"/>
  <s:Label text="{data.itemName}"/>
 </s:HGroup>
 
</s:ItemRenderer>

■ソースコード(ImageCacheクラス)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package myclasses
{
 import spark.core.ContentCache;
 
 public class ImageCache
 {
  private static var _instance:ImageCache;
  
  public var cache:ContentCache;
  
  public function ImageCache(s:Singleton, maxCacheEntries:int=100) {
   cache = new ContentCache();
   cache.maxCacheEntries = maxCacheEntries;
  }
  
  public static function getInstance(maxCacheEntries:int=100):ImageCache {
   if (ImageCache._instance == null) {
    ImageCache._instance = new ImageCache(new Singleton(), maxCacheEntries);
   }
   return ImageCache._instance;
  }
 }
}

class Singleton {}


http://corlan.org/2011/08/16/flex-mobile-development-caching-images-using-contentcache/
http://flexponential.com/2010/01/10/caching-images-loaded-from-a-spark-item-renderer/
http://flexponential.com/samples/DropDownListCaching/srcview/index.html

0 件のコメント:

コメントを投稿