7 Replies Latest reply on May 17, 2010 1:20 PM by Shongrunden

    Setting useVirtualLayout = true causes multiple issues (FB4/AIR)

    sleblang Level 1

      I have a SkinnableDataContainer which is using a TileLayout to display thumbnail images in an AIR application. In anticipation of having a large number of items, I would like to set the property - useVirtualLayout = true. However, I am running into an issue.

       

      For testing purposes, I have 15 thumbnail images being generated, and 10 being initially shown in the data container. Therefore, when the user scrolls the remaining 5 thumbnails will be shown. With useVirtualLayout set to 'true', only 10 itemrenderers should be created initially. However, what actually is happening is it is creating ~ 40+ itemrenderers (verified by tracing out in data_change handler). When I scroll to the remaining 5 thumbnails an additional even more renderers are created. I also notice a spike in the memory that the air application is using. If I set the useVirtualLayout = false, only 15 renderers are created and the memory is more manageable.


      Any suggestions on how to resolve this issue?


      Thanks.

        • 1. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
          Shongrunden Adobe Employee

          A dataChange event does not correspond to a renderer creation.  Virtual layout will set the data on a renderer many more times than non-virtual including as items come in and out of view.

           

          In this case you want to listen to creationComplete on the renderer in order to count how many renderer instances are actually being created.

          • 2. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
            sleblang Level 1

            Thanks for the information and prompt help.

             

            Using onCreationComplete does trace out far fewer instances of the renderer than using the dataChange handler. I was under the impression that all visual updates needed to be handled within the dataChange handler?  Once I moved the code that handles the visual updating to the onCreationComplete handler (in the itemrenderer), my issues with useVirtualLayout were pretty much resolved.

             

            How can I detect when an itemrenderer is being re-used? I need to do some clean-up of some objects.

             

            Thank you again for the assistance.

            • 3. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
              Shongrunden Adobe Employee

              Sorry I should have been more clear.  You're correct: you shouldn't key off of creationComplete in a renderer.  What you were doing with dataChange was correct, but I was just pointing out that it tells you nothing of how many renderers are actually created.

               

              You should see a few more renderers than what is initially visible created in order to support smooth scrolling.  I would expect it to be reasonable for 15 renderers to be created if your layout is showing two rows of five items each since if you scroll down a few pixels you will probably have 15 renderers in view.

               

              You can detect when an item renderer is being reused by setting and updating something like a "firstRun" flag in your dataChange handler.

               

              It might be useful for you to learn about how itemRendererFunction supports virtual layout without renderer recycling.  See this post as an example: http://flexponential.com/2009/07/10/performance-implications-of-the-list-itemrenderer-vs-i temrendererfunction-properties/

              • 4. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
                sleblang Level 1

                Thank you for the link. I will definitely take a look at it as I think it might be beneficial to me in this particular instance.

                 

                After further inspection, if I trace out in the creationComplete handler, the correct number of renderers are being created based upon what is visible on the screen. However, following up on your reply, I am slightly confused about using a 'firstRun' flag in the dataChange handler.  At what point would I set the flag to true, and then based upon what criteria would I check the flag?  The following trace statement is possibly adding to my confusion. As you can see from the trace statement below (from dataChange handler in the itemRenderer), it appears that there are multiple renderers for an image (#229 & #243 use the same image - yet I only have the image once in the dataProvider).

                 

                count - ThumbnailItemRenderer229: IMG_0478.JPG: 0
                count - ThumbnailItemRenderer229: IMG_0478.JPG: 1
                count - ThumbnailItemRenderer243: IMG_0478.JPG: 2
                count - ThumbnailItemRenderer243: IMG_0478.JPG: 3
                count - ThumbnailItemRenderer256: IMG_0248.JPG: 4
                count - ThumbnailItemRenderer256: IMG_0248.JPG: 5
                count - ThumbnailItemRenderer269: IMG_0230.JPG: 6
                count - ThumbnailItemRenderer269: IMG_0230.JPG: 7
                count - ThumbnailItemRenderer282: IMG_0460.JPG: 8
                count - ThumbnailItemRenderer282: IMG_0460.JPG: 9
                count - ThumbnailItemRenderer295: IMG_0498.JPG: 10
                count - ThumbnailItemRenderer295: IMG_0498.JPG: 11
                

                 

                Again, thank you for the prompt reply and assistance.

                • 5. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
                  Shongrunden Adobe Employee

                  dataChange is fired a lot.  Any time items come in and out of view the data gets set on those items, and sometimes even multiple times depending on your layout.

                   

                  Here is an example of how to set a flag to tell if the item has been in view.  Remember that renderers are recycled so we can't rely on any information in the renderer itself to decide whether or not an item has been seen before.  Instead we must keep track of this in the data item.

                   

                  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                                 xmlns:s="library://ns.adobe.com/flex/spark">
                     
                      <s:List height="90">
                          <s:dataProvider>
                              <s:ArrayCollection>
                                  <fx:Object title="Item 0" hasBeenInView="false" />
                                  <fx:Object title="Item 1" hasBeenInView="false" />
                                  <fx:Object title="Item 2" hasBeenInView="false" />
                                  <fx:Object title="Item 3" hasBeenInView="false" />
                                  <fx:Object title="Item 4" hasBeenInView="false" />
                                  <fx:Object title="Item 5" hasBeenInView="false" />
                              </s:ArrayCollection>
                          </s:dataProvider>
                          <s:itemRenderer>
                              <fx:Component>
                                  <s:ItemRenderer dataChange="init()" height="30">
                                      <fx:Script>
                                          <![CDATA[
                                              private function init():void {
                                                  if (data.hasBeenInView == false){
                                                      // this is the first time this data has come into view
                                                      trace("data: " + data.title);
                                                      data.hasBeenInView = true;
                                                  } else {
                                                      // this is a subsequent datachange
                                                     
                                                  }
                                                 
                                                  title.text = data.title as String;
                                              }
                                          ]]>
                                      </fx:Script>
                                      <s:Label id="title" verticalCenter="0" />
                                  </s:ItemRenderer>
                              </fx:Component>
                          </s:itemRenderer>
                      </s:List>
                  </s:Application>

                  • 7. Re: Setting useVirtualLayout = true causes multiple issues (FB4/AIR)
                    Shongrunden Adobe Employee

                    If you want to know when an item is going out of view you can listen for the hide event which is dispatched when the renderer has its visible property set to false:

                     

                    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                                   xmlns:s="library://ns.adobe.com/flex/spark">
                       
                        <s:List height="90">
                            <s:dataProvider>
                                <s:ArrayCollection>
                                    <fx:Object title="Item 0" hasBeenInView="false" />
                                    <fx:Object title="Item 1" hasBeenInView="false" />
                                    <fx:Object title="Item 2" hasBeenInView="false" />
                                    <fx:Object title="Item 3" hasBeenInView="false" />
                                    <fx:Object title="Item 4" hasBeenInView="false" />
                                    <fx:Object title="Item 5" hasBeenInView="false" />
                                </s:ArrayCollection>
                            </s:dataProvider>
                            <s:itemRenderer>
                                <fx:Component>
                                    <s:ItemRenderer dataChange="init()" hide="cleanup()" height="30">
                                        <fx:Script>
                                            <![CDATA[
                                                private function init():void {
                                                    if (data.hasBeenInView == false){
                                                        // this is the first time this data has come into view
                                                        trace("data: " + data.title);
                                                        data.hasBeenInView = true;
                                                    } else {
                                                        // this is a subsequent datachange
                                                       
                                                    }
                                                   
                                                    title.text = data.title as String;
                                                }
                                               
                                                private function cleanup():void {
                                                    // cleanup code for the data item currently in this renderer
                                                    trace('going out of view: ' + data.title);
                                                }
                                            ]]>
                                        </fx:Script>
                                        <s:Label id="title" verticalCenter="0" />
                                    </s:ItemRenderer>
                                </fx:Component>
                            </s:itemRenderer>
                        </s:List>
                    </s:Application>