ItemRenderer Switching URLLoader Images

2019-06-10 22:54发布

I don't even know how to explain this behavior but I'll try. I am loading images from an external url that requires basic auth so I am using URLLoader to load the image from a unique ID. The ID gets passed to the itemrenderer which then proceeds to load the image. But the images switch around on their own when I scroll. If I load more than 7 images or so it starts repeating images....

Youtube video of error: http://www.youtube.com/watch?v=ZYoqlS14gWQ

Relevant code:

<s:ItemRenderer name="RandomItemRenderer" creationComplete="init();"
            xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" 
            autoDrawBackground="false">
<s:states>
    <s:State name="normal" />
    <s:State name="hovered" />
    <s:State name="selected" />
</s:states>

<fx:Script>
    <![CDATA[
        import flash.net.URLLoader;
        import flash.net.URLLoaderDataFormat;
        import flash.net.URLRequest;
        import flash.net.URLRequestHeader;
        import flash.net.URLRequestMethod;

        import mx.utils.ObjectProxy;

        import customclasses.Settings;

        [Bindable] private var coverArtImage:Image;
        private var myCoverArtLoader:URLLoader;

        [Bindable] private var coverArtSource:String;

        private function init():void {
            get_coverArt();
        }

        private function get_coverArt(): void {
            if (!data.coverArt) {
                set_nullCoverArt();
            } else {
                var requestString:String = "/rest/getCoverArt.view?v=1.5.0&c=AirSub&id=" + data.coverArt;
                var requestURL:String = Settings.ServerURL + requestString;

                myCoverArtLoader = new URLLoader();
                var myRequest:URLRequest = new URLRequest();

                var authHeader:URLRequestHeader = new URLRequestHeader();
                authHeader.name = 'Authorization';
                authHeader.value = 'Basic ' + Settings.EncryptedCreds();

                myRequest.requestHeaders.push(authHeader);
                myRequest.url = requestURL;
                myRequest.method = URLRequestMethod.GET;
                myCoverArtLoader.dataFormat = URLLoaderDataFormat.BINARY;

                myCoverArtLoader.addEventListener(Event.COMPLETE, set_coverArt);
                myCoverArtLoader.addEventListener(IOErrorEvent.IO_ERROR, set_failedCoverArt);
                myCoverArtLoader.load(myRequest);
            }
        }

        private function set_coverArt(evt:Event) : void {
            coverArtImage = new Image();
            coverArtImage.source = myCoverArtLoader.data;           
            myCoverArtLoader.removeEventListener(Event.COMPLETE, set_coverArt);
        }

        private function set_nullCoverArt() : void {
            coverArtImage = new Image();
            coverArtImage.source = "assets/nullCoverArt.jpg";
        }

        private function set_failedCoverArt() : void {
            coverArtImage = new Image();
            coverArtImage.source = "assets/nullCoverArt.jpg";
            myCoverArtLoader.addEventListener(IOErrorEvent.IO_ERROR, set_nullCoverArt);
        }

    ]]>
</fx:Script>

<s:Image source.normal="assets/coverOutline.png" source.selected="assets/coverOutlineYellow.png" source.hovered="assets/coverOutlineYellow.png"
         height="226" width="226" />

<s:VGroup top="4.5" bottom="5" width="200" horizontalAlign="center" letterSpacing="10"
          paddingBottom="5" paddingTop="9" verticalAlign="middle" x="13.5">
    <s:Image id="ui_imgCoverArt" width="200" height="200" source="{coverArtImage.source}"/>
    <s:Label text="{data.title}" width="160" styleName="RandomList" />
</s:VGroup>

1条回答
何必那么认真
2楼-- · 2019-06-10 23:14

ItemRenderers are reusable and cached, i.e. there are only limited count created in List to fill its area (rowCount +- couple). And when you scroll, new renderers are not instantiated, instead the one renderer that was scrolled out goes up or down and is filled with new data.

That's why you can not rely on creationComplete event, it will be fired only once for each instance of renderer.

The solution is to override data setter and build there the behaviour needed:

override public function set data(value:Object):void
{
    super.data = value;
    get_coverArt();
}

Useful link: How flex itemRenderer works ? (their life cycle)

查看更多
登录 后发表回答