views:

688

answers:

1

I am using an component, and currently have a dataProvider working that is an ArrayCollection (have a separate question about how to make this an XML file... but I digress).

Variable declaration looks like this:

[Bindable]
private var _dpImageList : ArrayCollection = new ArrayCollection([
    {"location" : "path/to/image1.jpg"},
    {"location" : "path/to/image2.jpg"},
    {"location" : "path/to/image3.jpg"}
]);

I then refer to like this:

<s:List
    id="lstImages"
    width="100%"
    dataProvider="{_dpImageList}"
    itemRenderer="path.to.render.ImageRenderer"
    skinClass="path.to.skins.ListSkin"
    >
    <s:layout>
        <s:HorizontalLayout gap="2" />
    </s:layout>
</s:List>

Currently, it would appear that each item is processed asynchronously.

However, I want them to be processed synchronously.

Reason: I am displaying a list of images, and I want the leftmost one rendered first, followed by the one to its right, and so on.


Edit:

I just found this answer.
Do you think that could be the same issue?

+2  A: 

Instead of declaring the variable and using it as the binding source, declare two collections. Then, onCreationComplete call loadNext() which shifts an object out of the second array and pushes it into the first. When the item has been rendered (custom event dispatched by itemRenderer and caught) call loadNext() again until such time as your source array is empty and your bound dataProvider has all the images.

I can write it in code if this doesn't make any sense. ;)

<?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" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" creationComplete="init()">
    <fx:Script>
     <![CDATA[
      import mx.collections.ArrayCollection;
      [Bindable]
      private var _source : ArrayCollection = new ArrayCollection([
          {"location" : "path/to/image1.jpg"},
          {"location" : "path/to/image2.jpg"},
          {"location" : "path/to/image3.jpg"}
      ]);   

      [Bindable] private var dataProvider:ArrayCollection;

      protected function init():void
      {
       this.lstImages.addEventListener( "imageLoaded", handleImageLoaded);
       loadImage()
      }

      protected function loadImage():void
      {
       if(this._source.length<=0)
        return;
       var image:Object = this._source.getItemAt(0);
       dataProvider.addItem(image);
       this._source.removeItemAt(0);
      }

      protected function handleImageLoaded(event:Event):void
      {
       loadImage()
      }
     ]]>
    </fx:Script>
    <s:List
        id="lstImages"
        width="100%"
        dataProvider="{_dpImageList}"
        itemRenderer="path.to.render.ImageRenderer"
        skinClass="path.to.skins.ListSkin"
        >
        <s:layout>
            <s:HorizontalLayout gap="2" />
        </s:layout>
    </s:List>
</s:Application>

Your item renderer's image's complete handle will dispatch:

protected function handleImageLoaded(event:Event):void
{
    owner.dispatch(new Event("imageLoaded"));
}

And that should load your images in a clean sequence.

Joel Hooks
There are other ways to do this such as extending Image and have it control loading order. However, Joel's solution seems pretty simple. You might also be able to do this with a Cursor on the ArrayCollection.-James
James Ward
Thanks Joel.It almost makes sense, but would be really useful to see code demonstrating what you are describing!And to complicate matters, I am now reading the data in from an XML file; see here for details:http://stackoverflow.com/questions/1268351/how-do-i-set-the-dataprovider-for-an-slist-component-to-be-an-xml-file/1272490#1272490
Matt Calthrop
Sorry to bug you again Joel... do you have a moment to drop some source code in?cheers,Matt
Matt Calthrop
sorry Matt, I forgot about you. I think that should work :>
Joel Hooks
Thanks Joel... just trying to get my head around that - will have a go at implementing it soon!One thing: in your second piece of code, did you mean to write code that actually dispatches the event "imageLoaded"?Matt
Matt Calthrop
weird, I remember typing it correctly ;) - but yes - I updated it. You wat to use the item renderer's owner property so that the list is actually dispatching the event. This way you arn't messing with event bubbling and the events are easy to listen for.
Joel Hooks
I will make a working version and post it on my blog tonight if that would be more helpful.
Joel Hooks
That would be great Joel, thanks.
Matt Calthrop