You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ha...@apache.org on 2023/12/20 23:31:24 UTC
(royale-asjs) branch develop updated: Added factory for reusing data item renderers
This is an automated email from the ASF dual-hosted git repository.
harbs pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new 4e186b7442 Added factory for reusing data item renderers
4e186b7442 is described below
commit 4e186b7442872764e27f086a3a03863f09c599aa
Author: Harbs <ha...@in-tools.com>
AuthorDate: Thu Dec 21 01:31:18 2023 +0200
Added factory for reusing data item renderers
---
.../Basic/src/main/resources/basic-manifest.xml | 1 +
.../projects/Basic/src/main/royale/BasicClasses.as | 1 +
.../DataItemRendererFactoryForCollectionView.as | 2 +
...bleDataItemRendererFactoryForCollectionView.as} | 113 ++++++---------------
4 files changed, 34 insertions(+), 83 deletions(-)
diff --git a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
index dc0d7bfd00..51a682c0e4 100644
--- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
+++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
@@ -228,6 +228,7 @@
<component id="DynamicUpdateItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicUpdateItemRendererForArrayListData"/>
<component id="DataItemRendererFactoryForHierarchicalData" class="org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData" />
<component id="DataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView" />
+ <component id="ReusableDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollectionView" />
<component id="SelectionDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.SelectionDataItemRendererFactoryForCollectionView" />
<component id="DynamicRemoveAllItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllItemRendererForArrayListData" />
<component id="DynamicRemoveAllByNullItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRendererForArrayListData" />
diff --git a/frameworks/projects/Basic/src/main/royale/BasicClasses.as b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
index f5591dcad6..91a45a7911 100644
--- a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
+++ b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
@@ -245,6 +245,7 @@ internal class BasicClasses
import org.apache.royale.html.beads.DataItemRendererFactoryForArrayList; DataItemRendererFactoryForArrayList;
import org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData; DataItemRendererFactoryForHierarchicalData;
import org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView; DataItemRendererFactoryForCollectionView;
+ import org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollectionView; ReusableDataItemRendererFactoryForCollectionView;
import org.apache.royale.html.supportClasses.DataGroup; DataGroup;
import org.apache.royale.html.supportClasses.Border; Border;
import org.apache.royale.html.supportClasses.Viewport; Viewport;
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
index de128b771e..07b387c7a0 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
@@ -77,6 +77,7 @@ package org.apache.royale.html.beads
* @royaleignorecoercion org.apache.royale.collections.ICollectionView
* @royaleignorecoercion org.apache.royale.core.IListPresentationModel
* @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
+ * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
* @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
* @royaleignorecoercion org.apache.royale.html.beads.IListView
*/
@@ -152,6 +153,7 @@ package org.apache.royale.html.beads
* @private
* @royaleignorecoercion org.apache.royale.collections.ICollectionView
* @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
+ * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
* @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
* @royaleignorecoercion org.apache.royale.html.beads.IListView
*/
diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
similarity index 58%
copy from frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
copy to frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
index de128b771e..d697b26632 100644
--- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
+++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
@@ -18,76 +18,55 @@
////////////////////////////////////////////////////////////////////////////////
package org.apache.royale.html.beads
{
+ import org.apache.royale.utils.sendStrandEvent;
+ import org.apache.royale.events.CollectionEvent;
+ import org.apache.royale.core.IStrandWithModelView;
import org.apache.royale.core.IIndexedItemRenderer;
import org.apache.royale.core.IIndexedItemRendererInitializer;
import org.apache.royale.core.IItemRendererOwnerView;
- import org.apache.royale.core.IStrandWithModelView;
- import org.apache.royale.events.CollectionEvent;
- import org.apache.royale.events.Event;
- import org.apache.royale.events.IEventDispatcher;
- import org.apache.royale.html.beads.IListView;
- import org.apache.royale.utils.sendStrandEvent;
-
/**
- * This class creates itemRenderer instances from the data contained within an ICollectionView
+ * The ReusableDataItemRendererFactoryForCollectionView class will save removed itemRenderers
+ * and reuse them when new item renderers are needed. This is useful for large collections
+ * where creating new item renderers can be expensive. Using this class can drastically
+ * reduce rendering time at the expense of preventing the unused item renderers from being
+ * garbage collected.
+ *
+ * In an unscientific test, using this class reduced rendering time by about a factor of 100 in some cases.
+ *
+ * Item renderers must be able to be reused. Resetting the data property must properly reset the state and
+ * clean any event listeners from the old state.
*/
- public class DataItemRendererFactoryForCollectionView extends DataItemRendererFactoryBase
+ public class ReusableDataItemRendererFactoryForCollectionView extends DataItemRendererFactoryForCollectionView
{
- public function DataItemRendererFactoryForCollectionView(target:Object = null)
+ public function ReusableDataItemRendererFactoryForCollectionView(target:Object = null)
{
super(target);
}
-
- /**
- * the dataProvider as a dispatcher
- */
- protected var dped:IEventDispatcher;
+
+ private var _unusedRenderers:Array = [];
/**
* @private
* @royaleignorecoercion org.apache.royale.collections.ICollectionView
* @royaleignorecoercion org.apache.royale.core.IListPresentationModel
* @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
- * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
- */
- override protected function dataProviderChangeHandler(event:Event):void
- {
- super.dataProviderChangeHandler(event);
-
- if(dped)
- {
- dped.removeEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
- dped.removeEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
- dped.removeEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
- dped = null;
- }
-
- if (!dataProviderModel.dataProvider)
- return;
-
- // listen for individual items being added in the future.
- dped = dataProviderModel.dataProvider as IEventDispatcher;
- dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
- dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
- dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
- }
-
- /**
- * @private
- * @royaleignorecoercion org.apache.royale.collections.ICollectionView
- * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
- * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
+ * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
* @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
* @royaleignorecoercion org.apache.royale.html.beads.IListView
*/
- protected function itemAddedHandler(event:CollectionEvent):void
+ override protected function itemAddedHandler(event:CollectionEvent):void
{
if(!dataProviderExist)
return;
var view:IListView = (_strand as IStrandWithModelView).view as IListView;
var dataGroup:IItemRendererOwnerView = view.dataGroup;
- var ir:IIndexedItemRenderer = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
+ var ir:IIndexedItemRenderer;
+ if(_unusedRenderers.length > 0)
+ ir = _unusedRenderers.pop();
+
+ else
+ ir = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
var data:Object = event.item;
dataGroup.addItemRendererAt(ir, event.index);
@@ -108,7 +87,8 @@ package org.apache.royale.html.beads
}
sendStrandEvent(_strand,"itemsCreated");
- sendStrandEvent(_strand,"layoutNeeded");
+ // The itemsCreated handler sends layoutNeeded, so no need to do it here.
+ // sendStrandEvent(_strand,"layoutNeeded");
}
/**
@@ -119,7 +99,7 @@ package org.apache.royale.html.beads
* @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
* @royaleignorecoercion org.apache.royale.html.beads.IListView
*/
- protected function itemRemovedHandler(event:CollectionEvent):void
+ override protected function itemRemovedHandler(event:CollectionEvent):void
{
if(!dataProviderExist)
return;
@@ -130,7 +110,7 @@ package org.apache.royale.html.beads
var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
if (!ir) return; // may have already been cleaned up, possibly when a tree node closes
dataGroup.removeItemRenderer(ir);
-
+ _unusedRenderers.push(ir);
// adjust the itemRenderers' index to adjust for the shift
var n:int = dataGroup.numItemRenderers;
for (var i:int = event.index; i < n; i++)
@@ -147,39 +127,6 @@ package org.apache.royale.html.beads
sendStrandEvent(_strand,"layoutNeeded");
}
-
- /**
- * @private
- * @royaleignorecoercion org.apache.royale.collections.ICollectionView
- * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
- * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
- * @royaleignorecoercion org.apache.royale.html.beads.IListView
- */
- protected function itemUpdatedHandler(event:CollectionEvent):void
- {
- if(!dataProviderExist)
- return;
-
- var view:IListView = (_strand as IStrandWithModelView).view as IListView;
- var dataGroup:IItemRendererOwnerView = view.dataGroup;
-
- // update the given renderer with (possibly) new information so it can change its
- // appearence or whatever.
- var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
-
- var data:Object = event.item;
- (itemRendererInitializer as IIndexedItemRendererInitializer).initializeIndexedItemRenderer(ir, data, event.index);
- ir.data = data;
- }
-
- override protected function get dataProviderLength():int
- {
- return dataProviderModel.dataProvider.length;
- }
-
- override protected function getItemAt(i:int):Object
- {
- return dataProviderModel.dataProvider.getItemAt(i);
- }
+
}
}
\ No newline at end of file
Re: (royale-asjs) branch develop updated: Added factory for reusing data item renderers
Posted by Harbs <ha...@gmail.com>.
In Royale, by default any time you use “as”, the compiler will insert a “Language.as” function call to coerce the variable and it will become null if the variable is the wrong type.
While this ensures type safety and is sometimes useful, it can add overhead which can effect preforance particularly in places where it’s called a lot.
In the framework code, I have tried to add @royaleignorecoercion where the coercion is not needed and @royaleemitcoercion where it is needed to be explicit about it. Those comment effect the behavior of the compiler.
Using “assert" is much better for forcing specific types because those calls are optimized out in the release builds.
HTH,
Harbs
> On Dec 21, 2023, at 11:14 AM, Maria Jose Esteve <mj...@iest.com> wrote:
>
> Harb, can you explain to me the importance/need for @royaleignorecoercion?
>
> Hiedra
>
> -----Mensaje original-----
> De: Harbs <ha...@gmail.com>
> Enviado el: jueves, 21 de diciembre de 2023 0:35
> Para: Apache Royale Development <de...@royale.apache.org>
> Asunto: Re: (royale-asjs) branch develop updated: Added factory for reusing data item renderers
>
> FYI, this class had a drastic effect on a tree I was working on. Expanding a node went from taking between 1 and 2 seconds to taking about 20ms.
>
> I also committed a number of other performance optimizations relating specifically to trees. It’s now possible to create a custom implementation for getting the depth of nodes which is very expensive in the built-in method.
>
> Harbs
>
>> On Dec 21, 2023, at 1:31 AM, harbs@apache.org wrote:
>>
>> This is an automated email from the ASF dual-hosted git repository.
>>
>> harbs pushed a commit to branch develop in repository
>> https://gitbox.apache.org/repos/asf/royale-asjs.git
>>
>>
>> The following commit(s) were added to refs/heads/develop by this push:
>> new 4e186b7442 Added factory for reusing data item renderers
>> 4e186b7442 is described below
>>
>> commit 4e186b7442872764e27f086a3a03863f09c599aa
>> Author: Harbs <ha...@in-tools.com>
>> AuthorDate: Thu Dec 21 01:31:18 2023 +0200
>>
>> Added factory for reusing data item renderers
>> ---
>> .../Basic/src/main/resources/basic-manifest.xml | 1 +
>> .../projects/Basic/src/main/royale/BasicClasses.as | 1 +
>> .../DataItemRendererFactoryForCollectionView.as | 2 +
>> ...bleDataItemRendererFactoryForCollectionView.as} | 113
>> ++++++---------------
>> 4 files changed, 34 insertions(+), 83 deletions(-)
>>
>> diff --git
>> a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
>> b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
>> index dc0d7bfd00..51a682c0e4 100644
>> --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
>> +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
>> @@ -228,6 +228,7 @@
>> <component id="DynamicUpdateItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicUpdateItemRendererForArrayListData"/>
>> <component id="DataItemRendererFactoryForHierarchicalData" class="org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData" />
>> <component id="DataItemRendererFactoryForCollectionView"
>> class="org.apache.royale.html.beads.DataItemRendererFactoryForCollecti
>> onView" />
>> + <component id="ReusableDataItemRendererFactoryForCollectionView"
>> + class="org.apache.royale.html.beads.ReusableDataItemRendererFactoryF
>> + orCollectionView" />
>> <component id="SelectionDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.SelectionDataItemRendererFactoryForCollectionView" />
>> <component id="DynamicRemoveAllItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllItemRendererForArrayListData" />
>> <component id="DynamicRemoveAllByNullItemRendererForArrayListData"
>> class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRenderer
>> ForArrayListData" /> diff --git
>> a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
>> b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
>> index f5591dcad6..91a45a7911 100644
>> --- a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
>> +++ b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
>> @@ -245,6 +245,7 @@ internal class BasicClasses
>> import org.apache.royale.html.beads.DataItemRendererFactoryForArrayList; DataItemRendererFactoryForArrayList;
>> import org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData; DataItemRendererFactoryForHierarchicalData;
>> import
>> org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView;
>> DataItemRendererFactoryForCollectionView;
>> + import
>> +org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollec
>> +tionView; ReusableDataItemRendererFactoryForCollectionView;
>> import org.apache.royale.html.supportClasses.DataGroup; DataGroup;
>> import org.apache.royale.html.supportClasses.Border; Border;
>> import org.apache.royale.html.supportClasses.Viewport; Viewport; diff
>> --git
>> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/DataItemRendererFactoryForCollectionView.as
>> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/DataItemRendererFactoryForCollectionView.as
>> index de128b771e..07b387c7a0 100644
>> ---
>> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/DataItemRendererFactoryForCollectionView.as
>> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html
>> +++ /beads/DataItemRendererFactoryForCollectionView.as
>> @@ -77,6 +77,7 @@ package org.apache.royale.html.beads
>> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
>> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
>> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
>> + * @royaleignorecoercion
>> +org.apache.royale.core.IIndexedItemRendererInitializer
>> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
>> * @royaleignorecoercion org.apache.royale.html.beads.IListView
>> */
>> @@ -152,6 +153,7 @@ package org.apache.royale.html.beads
>> * @private
>> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
>> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
>> + * @royaleignorecoercion
>> +org.apache.royale.core.IIndexedItemRendererInitializer
>> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
>> * @royaleignorecoercion org.apache.royale.html.beads.IListView
>> */
>> diff --git
>> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/DataItemRendererFactoryForCollectionView.as
>> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/ReusableDataItemRendererFactoryForCollectionView.as
>> similarity index 58%
>> copy from
>> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads
>> /DataItemRendererFactoryForCollectionView.as
>> copy to
>> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads
>> /ReusableDataItemRendererFactoryForCollectionView.as
>> index de128b771e..d697b26632 100644
>> ---
>> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
>> ds/DataItemRendererFactoryForCollectionView.as
>> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html
>> +++ /beads/ReusableDataItemRendererFactoryForCollectionView.as
>> @@ -18,76 +18,55 @@
>> //////////////////////////////////////////////////////////////////////
>> //////////
>> package org.apache.royale.html.beads
>> {
>> + import org.apache.royale.utils.sendStrandEvent;
>> + import org.apache.royale.events.CollectionEvent;
>> + import org.apache.royale.core.IStrandWithModelView;
>> import org.apache.royale.core.IIndexedItemRenderer;
>> import org.apache.royale.core.IIndexedItemRendererInitializer;
>> import org.apache.royale.core.IItemRendererOwnerView;
>> - import org.apache.royale.core.IStrandWithModelView;
>> - import org.apache.royale.events.CollectionEvent;
>> - import org.apache.royale.events.Event;
>> - import org.apache.royale.events.IEventDispatcher;
>> - import org.apache.royale.html.beads.IListView;
>> - import org.apache.royale.utils.sendStrandEvent;
>> -
>> /**
>> - * This class creates itemRenderer instances from the data contained within an ICollectionView
>> + * The ReusableDataItemRendererFactoryForCollectionView class will save removed itemRenderers
>> + * and reuse them when new item renderers are needed. This is useful for large collections
>> + * where creating new item renderers can be expensive. Using this class can drastically
>> + * reduce rendering time at the expense of preventing the unused item renderers from being
>> + * garbage collected.
>> + *
>> + * In an unscientific test, using this class reduced rendering time by about a factor of 100 in some cases.
>> + *
>> + * Item renderers must be able to be reused. Resetting the data property must properly reset the state and
>> + * clean any event listeners from the old state.
>> */
>> - public class DataItemRendererFactoryForCollectionView extends DataItemRendererFactoryBase
>> + public class ReusableDataItemRendererFactoryForCollectionView
>> +extends DataItemRendererFactoryForCollectionView
>> {
>> - public function DataItemRendererFactoryForCollectionView(target:Object = null)
>> + public function
>> +ReusableDataItemRendererFactoryForCollectionView(target:Object =
>> +null)
>> {
>> super(target);
>> }
>> -
>> - /**
>> - * the dataProvider as a dispatcher
>> - */
>> - protected var dped:IEventDispatcher;
>> +
>> + private var _unusedRenderers:Array = [];
>>
>> /**
>> * @private
>> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
>> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
>> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
>> - * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
>> - */
>> - override protected function dataProviderChangeHandler(event:Event):void
>> - {
>> - super.dataProviderChangeHandler(event);
>> -
>> - if(dped)
>> - {
>> - dped.removeEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
>> - dped.removeEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
>> - dped.removeEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
>> - dped = null;
>> - }
>> -
>> - if (!dataProviderModel.dataProvider)
>> - return;
>> -
>> - // listen for individual items being added in the future.
>> - dped = dataProviderModel.dataProvider as IEventDispatcher;
>> - dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
>> - dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
>> - dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
>> - }
>> -
>> - /**
>> - * @private
>> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
>> - * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
>> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
>> + * @royaleignorecoercion
>> +org.apache.royale.core.IIndexedItemRendererInitializer
>> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
>> * @royaleignorecoercion org.apache.royale.html.beads.IListView
>> */
>> - protected function itemAddedHandler(event:CollectionEvent):void
>> + override protected function
>> +itemAddedHandler(event:CollectionEvent):void
>> {
>> if(!dataProviderExist)
>> return;
>> var view:IListView = (_strand as IStrandWithModelView).view as IListView;
>> var dataGroup:IItemRendererOwnerView = view.dataGroup;
>>
>> - var ir:IIndexedItemRenderer = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
>> + var ir:IIndexedItemRenderer;
>> + if(_unusedRenderers.length > 0)
>> + ir = _unusedRenderers.pop();
>> +
>> + else
>> + ir = itemRendererFactory.createItemRenderer() as
>> +IIndexedItemRenderer;
>>
>> var data:Object = event.item;
>> dataGroup.addItemRendererAt(ir, event.index); @@ -108,7 +87,8 @@
>> package org.apache.royale.html.beads
>> }
>>
>> sendStrandEvent(_strand,"itemsCreated");
>> - sendStrandEvent(_strand,"layoutNeeded");
>> + // The itemsCreated handler sends layoutNeeded, so no need to do it here.
>> + // sendStrandEvent(_strand,"layoutNeeded");
>> }
>>
>> /**
>> @@ -119,7 +99,7 @@ package org.apache.royale.html.beads
>> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
>> * @royaleignorecoercion org.apache.royale.html.beads.IListView
>> */
>> - protected function itemRemovedHandler(event:CollectionEvent):void
>> + override protected function
>> +itemRemovedHandler(event:CollectionEvent):void
>> {
>> if(!dataProviderExist)
>> return;
>> @@ -130,7 +110,7 @@ package org.apache.royale.html.beads
>> var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
>> if (!ir) return; // may have already been cleaned up, possibly when a tree node closes
>> dataGroup.removeItemRenderer(ir);
>> -
>> + _unusedRenderers.push(ir);
>> // adjust the itemRenderers' index to adjust for the shift
>> var n:int = dataGroup.numItemRenderers;
>> for (var i:int = event.index; i < n; i++) @@ -147,39 +127,6 @@
>> package org.apache.royale.html.beads
>>
>> sendStrandEvent(_strand,"layoutNeeded");
>> }
>> -
>> - /**
>> - * @private
>> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
>> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
>> - * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
>> - * @royaleignorecoercion org.apache.royale.html.beads.IListView
>> - */
>> - protected function itemUpdatedHandler(event:CollectionEvent):void
>> - {
>> - if(!dataProviderExist)
>> - return;
>> -
>> - var view:IListView = (_strand as IStrandWithModelView).view as IListView;
>> - var dataGroup:IItemRendererOwnerView = view.dataGroup;
>> -
>> - // update the given renderer with (possibly) new information so it can change its
>> - // appearence or whatever.
>> - var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
>> -
>> - var data:Object = event.item;
>> - (itemRendererInitializer as IIndexedItemRendererInitializer).initializeIndexedItemRenderer(ir, data, event.index);
>> - ir.data = data;
>> - }
>> -
>> - override protected function get dataProviderLength():int
>> - {
>> - return dataProviderModel.dataProvider.length;
>> - }
>> -
>> - override protected function getItemAt(i:int):Object
>> - {
>> - return dataProviderModel.dataProvider.getItemAt(i);
>> - }
>> +
>> }
>> }
>> \ No newline at end of file
>>
>
RE: (royale-asjs) branch develop updated: Added factory for reusing data item renderers
Posted by Maria Jose Esteve <mj...@iest.com>.
Harb, can you explain to me the importance/need for @royaleignorecoercion?
Hiedra
-----Mensaje original-----
De: Harbs <ha...@gmail.com>
Enviado el: jueves, 21 de diciembre de 2023 0:35
Para: Apache Royale Development <de...@royale.apache.org>
Asunto: Re: (royale-asjs) branch develop updated: Added factory for reusing data item renderers
FYI, this class had a drastic effect on a tree I was working on. Expanding a node went from taking between 1 and 2 seconds to taking about 20ms.
I also committed a number of other performance optimizations relating specifically to trees. It’s now possible to create a custom implementation for getting the depth of nodes which is very expensive in the built-in method.
Harbs
> On Dec 21, 2023, at 1:31 AM, harbs@apache.org wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> harbs pushed a commit to branch develop in repository
> https://gitbox.apache.org/repos/asf/royale-asjs.git
>
>
> The following commit(s) were added to refs/heads/develop by this push:
> new 4e186b7442 Added factory for reusing data item renderers
> 4e186b7442 is described below
>
> commit 4e186b7442872764e27f086a3a03863f09c599aa
> Author: Harbs <ha...@in-tools.com>
> AuthorDate: Thu Dec 21 01:31:18 2023 +0200
>
> Added factory for reusing data item renderers
> ---
> .../Basic/src/main/resources/basic-manifest.xml | 1 +
> .../projects/Basic/src/main/royale/BasicClasses.as | 1 +
> .../DataItemRendererFactoryForCollectionView.as | 2 +
> ...bleDataItemRendererFactoryForCollectionView.as} | 113
> ++++++---------------
> 4 files changed, 34 insertions(+), 83 deletions(-)
>
> diff --git
> a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> index dc0d7bfd00..51a682c0e4 100644
> --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> @@ -228,6 +228,7 @@
> <component id="DynamicUpdateItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicUpdateItemRendererForArrayListData"/>
> <component id="DataItemRendererFactoryForHierarchicalData" class="org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData" />
> <component id="DataItemRendererFactoryForCollectionView"
> class="org.apache.royale.html.beads.DataItemRendererFactoryForCollecti
> onView" />
> + <component id="ReusableDataItemRendererFactoryForCollectionView"
> + class="org.apache.royale.html.beads.ReusableDataItemRendererFactoryF
> + orCollectionView" />
> <component id="SelectionDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.SelectionDataItemRendererFactoryForCollectionView" />
> <component id="DynamicRemoveAllItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllItemRendererForArrayListData" />
> <component id="DynamicRemoveAllByNullItemRendererForArrayListData"
> class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRenderer
> ForArrayListData" /> diff --git
> a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> index f5591dcad6..91a45a7911 100644
> --- a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> +++ b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> @@ -245,6 +245,7 @@ internal class BasicClasses
> import org.apache.royale.html.beads.DataItemRendererFactoryForArrayList; DataItemRendererFactoryForArrayList;
> import org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData; DataItemRendererFactoryForHierarchicalData;
> import
> org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView;
> DataItemRendererFactoryForCollectionView;
> + import
> +org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollec
> +tionView; ReusableDataItemRendererFactoryForCollectionView;
> import org.apache.royale.html.supportClasses.DataGroup; DataGroup;
> import org.apache.royale.html.supportClasses.Border; Border;
> import org.apache.royale.html.supportClasses.Viewport; Viewport; diff
> --git
> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/DataItemRendererFactoryForCollectionView.as
> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/DataItemRendererFactoryForCollectionView.as
> index de128b771e..07b387c7a0 100644
> ---
> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/DataItemRendererFactoryForCollectionView.as
> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html
> +++ /beads/DataItemRendererFactoryForCollectionView.as
> @@ -77,6 +77,7 @@ package org.apache.royale.html.beads
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion
> +org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> @@ -152,6 +153,7 @@ package org.apache.royale.html.beads
> * @private
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion
> +org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> diff --git
> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/DataItemRendererFactoryForCollectionView.as
> b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/ReusableDataItemRendererFactoryForCollectionView.as
> similarity index 58%
> copy from
> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads
> /DataItemRendererFactoryForCollectionView.as
> copy to
> frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads
> /ReusableDataItemRendererFactoryForCollectionView.as
> index de128b771e..d697b26632 100644
> ---
> a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/bea
> ds/DataItemRendererFactoryForCollectionView.as
> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html
> +++ /beads/ReusableDataItemRendererFactoryForCollectionView.as
> @@ -18,76 +18,55 @@
> //////////////////////////////////////////////////////////////////////
> //////////
> package org.apache.royale.html.beads
> {
> + import org.apache.royale.utils.sendStrandEvent;
> + import org.apache.royale.events.CollectionEvent;
> + import org.apache.royale.core.IStrandWithModelView;
> import org.apache.royale.core.IIndexedItemRenderer;
> import org.apache.royale.core.IIndexedItemRendererInitializer;
> import org.apache.royale.core.IItemRendererOwnerView;
> - import org.apache.royale.core.IStrandWithModelView;
> - import org.apache.royale.events.CollectionEvent;
> - import org.apache.royale.events.Event;
> - import org.apache.royale.events.IEventDispatcher;
> - import org.apache.royale.html.beads.IListView;
> - import org.apache.royale.utils.sendStrandEvent;
> -
> /**
> - * This class creates itemRenderer instances from the data contained within an ICollectionView
> + * The ReusableDataItemRendererFactoryForCollectionView class will save removed itemRenderers
> + * and reuse them when new item renderers are needed. This is useful for large collections
> + * where creating new item renderers can be expensive. Using this class can drastically
> + * reduce rendering time at the expense of preventing the unused item renderers from being
> + * garbage collected.
> + *
> + * In an unscientific test, using this class reduced rendering time by about a factor of 100 in some cases.
> + *
> + * Item renderers must be able to be reused. Resetting the data property must properly reset the state and
> + * clean any event listeners from the old state.
> */
> - public class DataItemRendererFactoryForCollectionView extends DataItemRendererFactoryBase
> + public class ReusableDataItemRendererFactoryForCollectionView
> +extends DataItemRendererFactoryForCollectionView
> {
> - public function DataItemRendererFactoryForCollectionView(target:Object = null)
> + public function
> +ReusableDataItemRendererFactoryForCollectionView(target:Object =
> +null)
> {
> super(target);
> }
> -
> - /**
> - * the dataProvider as a dispatcher
> - */
> - protected var dped:IEventDispatcher;
> +
> + private var _unusedRenderers:Array = [];
>
> /**
> * @private
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> - * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
> - */
> - override protected function dataProviderChangeHandler(event:Event):void
> - {
> - super.dataProviderChangeHandler(event);
> -
> - if(dped)
> - {
> - dped.removeEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
> - dped.removeEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
> - dped.removeEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
> - dped = null;
> - }
> -
> - if (!dataProviderModel.dataProvider)
> - return;
> -
> - // listen for individual items being added in the future.
> - dped = dataProviderModel.dataProvider as IEventDispatcher;
> - dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
> - dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
> - dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
> - }
> -
> - /**
> - * @private
> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> - * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion
> +org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> - protected function itemAddedHandler(event:CollectionEvent):void
> + override protected function
> +itemAddedHandler(event:CollectionEvent):void
> {
> if(!dataProviderExist)
> return;
> var view:IListView = (_strand as IStrandWithModelView).view as IListView;
> var dataGroup:IItemRendererOwnerView = view.dataGroup;
>
> - var ir:IIndexedItemRenderer = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
> + var ir:IIndexedItemRenderer;
> + if(_unusedRenderers.length > 0)
> + ir = _unusedRenderers.pop();
> +
> + else
> + ir = itemRendererFactory.createItemRenderer() as
> +IIndexedItemRenderer;
>
> var data:Object = event.item;
> dataGroup.addItemRendererAt(ir, event.index); @@ -108,7 +87,8 @@
> package org.apache.royale.html.beads
> }
>
> sendStrandEvent(_strand,"itemsCreated");
> - sendStrandEvent(_strand,"layoutNeeded");
> + // The itemsCreated handler sends layoutNeeded, so no need to do it here.
> + // sendStrandEvent(_strand,"layoutNeeded");
> }
>
> /**
> @@ -119,7 +99,7 @@ package org.apache.royale.html.beads
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> - protected function itemRemovedHandler(event:CollectionEvent):void
> + override protected function
> +itemRemovedHandler(event:CollectionEvent):void
> {
> if(!dataProviderExist)
> return;
> @@ -130,7 +110,7 @@ package org.apache.royale.html.beads
> var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
> if (!ir) return; // may have already been cleaned up, possibly when a tree node closes
> dataGroup.removeItemRenderer(ir);
> -
> + _unusedRenderers.push(ir);
> // adjust the itemRenderers' index to adjust for the shift
> var n:int = dataGroup.numItemRenderers;
> for (var i:int = event.index; i < n; i++) @@ -147,39 +127,6 @@
> package org.apache.royale.html.beads
>
> sendStrandEvent(_strand,"layoutNeeded");
> }
> -
> - /**
> - * @private
> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> - * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> - * @royaleignorecoercion org.apache.royale.html.beads.IListView
> - */
> - protected function itemUpdatedHandler(event:CollectionEvent):void
> - {
> - if(!dataProviderExist)
> - return;
> -
> - var view:IListView = (_strand as IStrandWithModelView).view as IListView;
> - var dataGroup:IItemRendererOwnerView = view.dataGroup;
> -
> - // update the given renderer with (possibly) new information so it can change its
> - // appearence or whatever.
> - var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
> -
> - var data:Object = event.item;
> - (itemRendererInitializer as IIndexedItemRendererInitializer).initializeIndexedItemRenderer(ir, data, event.index);
> - ir.data = data;
> - }
> -
> - override protected function get dataProviderLength():int
> - {
> - return dataProviderModel.dataProvider.length;
> - }
> -
> - override protected function getItemAt(i:int):Object
> - {
> - return dataProviderModel.dataProvider.getItemAt(i);
> - }
> +
> }
> }
> \ No newline at end of file
>
Re: (royale-asjs) branch develop updated: Added factory for reusing data item renderers
Posted by Harbs <ha...@gmail.com>.
FYI, this class had a drastic effect on a tree I was working on. Expanding a node went from taking between 1 and 2 seconds to taking about 20ms.
I also committed a number of other performance optimizations relating specifically to trees. It’s now possible to create a custom implementation for getting the depth of nodes which is very expensive in the built-in method.
Harbs
> On Dec 21, 2023, at 1:31 AM, harbs@apache.org wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> harbs pushed a commit to branch develop
> in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
>
>
> The following commit(s) were added to refs/heads/develop by this push:
> new 4e186b7442 Added factory for reusing data item renderers
> 4e186b7442 is described below
>
> commit 4e186b7442872764e27f086a3a03863f09c599aa
> Author: Harbs <ha...@in-tools.com>
> AuthorDate: Thu Dec 21 01:31:18 2023 +0200
>
> Added factory for reusing data item renderers
> ---
> .../Basic/src/main/resources/basic-manifest.xml | 1 +
> .../projects/Basic/src/main/royale/BasicClasses.as | 1 +
> .../DataItemRendererFactoryForCollectionView.as | 2 +
> ...bleDataItemRendererFactoryForCollectionView.as} | 113 ++++++---------------
> 4 files changed, 34 insertions(+), 83 deletions(-)
>
> diff --git a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> index dc0d7bfd00..51a682c0e4 100644
> --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> @@ -228,6 +228,7 @@
> <component id="DynamicUpdateItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicUpdateItemRendererForArrayListData"/>
> <component id="DataItemRendererFactoryForHierarchicalData" class="org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData" />
> <component id="DataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView" />
> + <component id="ReusableDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollectionView" />
> <component id="SelectionDataItemRendererFactoryForCollectionView" class="org.apache.royale.html.beads.SelectionDataItemRendererFactoryForCollectionView" />
> <component id="DynamicRemoveAllItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllItemRendererForArrayListData" />
> <component id="DynamicRemoveAllByNullItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRendererForArrayListData" />
> diff --git a/frameworks/projects/Basic/src/main/royale/BasicClasses.as b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> index f5591dcad6..91a45a7911 100644
> --- a/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> +++ b/frameworks/projects/Basic/src/main/royale/BasicClasses.as
> @@ -245,6 +245,7 @@ internal class BasicClasses
> import org.apache.royale.html.beads.DataItemRendererFactoryForArrayList; DataItemRendererFactoryForArrayList;
> import org.apache.royale.html.beads.DataItemRendererFactoryForHierarchicalData; DataItemRendererFactoryForHierarchicalData;
> import org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView; DataItemRendererFactoryForCollectionView;
> + import org.apache.royale.html.beads.ReusableDataItemRendererFactoryForCollectionView; ReusableDataItemRendererFactoryForCollectionView;
> import org.apache.royale.html.supportClasses.DataGroup; DataGroup;
> import org.apache.royale.html.supportClasses.Border; Border;
> import org.apache.royale.html.supportClasses.Viewport; Viewport;
> diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
> index de128b771e..07b387c7a0 100644
> --- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
> @@ -77,6 +77,7 @@ package org.apache.royale.html.beads
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> @@ -152,6 +153,7 @@ package org.apache.royale.html.beads
> * @private
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
> similarity index 58%
> copy from frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
> copy to frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
> index de128b771e..d697b26632 100644
> --- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/DataItemRendererFactoryForCollectionView.as
> +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/ReusableDataItemRendererFactoryForCollectionView.as
> @@ -18,76 +18,55 @@
> ////////////////////////////////////////////////////////////////////////////////
> package org.apache.royale.html.beads
> {
> + import org.apache.royale.utils.sendStrandEvent;
> + import org.apache.royale.events.CollectionEvent;
> + import org.apache.royale.core.IStrandWithModelView;
> import org.apache.royale.core.IIndexedItemRenderer;
> import org.apache.royale.core.IIndexedItemRendererInitializer;
> import org.apache.royale.core.IItemRendererOwnerView;
> - import org.apache.royale.core.IStrandWithModelView;
> - import org.apache.royale.events.CollectionEvent;
> - import org.apache.royale.events.Event;
> - import org.apache.royale.events.IEventDispatcher;
> - import org.apache.royale.html.beads.IListView;
> - import org.apache.royale.utils.sendStrandEvent;
> -
> /**
> - * This class creates itemRenderer instances from the data contained within an ICollectionView
> + * The ReusableDataItemRendererFactoryForCollectionView class will save removed itemRenderers
> + * and reuse them when new item renderers are needed. This is useful for large collections
> + * where creating new item renderers can be expensive. Using this class can drastically
> + * reduce rendering time at the expense of preventing the unused item renderers from being
> + * garbage collected.
> + *
> + * In an unscientific test, using this class reduced rendering time by about a factor of 100 in some cases.
> + *
> + * Item renderers must be able to be reused. Resetting the data property must properly reset the state and
> + * clean any event listeners from the old state.
> */
> - public class DataItemRendererFactoryForCollectionView extends DataItemRendererFactoryBase
> + public class ReusableDataItemRendererFactoryForCollectionView extends DataItemRendererFactoryForCollectionView
> {
> - public function DataItemRendererFactoryForCollectionView(target:Object = null)
> + public function ReusableDataItemRendererFactoryForCollectionView(target:Object = null)
> {
> super(target);
> }
> -
> - /**
> - * the dataProvider as a dispatcher
> - */
> - protected var dped:IEventDispatcher;
> +
> + private var _unusedRenderers:Array = [];
>
> /**
> * @private
> * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> - * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
> - */
> - override protected function dataProviderChangeHandler(event:Event):void
> - {
> - super.dataProviderChangeHandler(event);
> -
> - if(dped)
> - {
> - dped.removeEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
> - dped.removeEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
> - dped.removeEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
> - dped = null;
> - }
> -
> - if (!dataProviderModel.dataProvider)
> - return;
> -
> - // listen for individual items being added in the future.
> - dped = dataProviderModel.dataProvider as IEventDispatcher;
> - dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
> - dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
> - dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
> - }
> -
> - /**
> - * @private
> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> - * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> + * @royaleignorecoercion org.apache.royale.core.IIndexedItemRendererInitializer
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> - protected function itemAddedHandler(event:CollectionEvent):void
> + override protected function itemAddedHandler(event:CollectionEvent):void
> {
> if(!dataProviderExist)
> return;
> var view:IListView = (_strand as IStrandWithModelView).view as IListView;
> var dataGroup:IItemRendererOwnerView = view.dataGroup;
>
> - var ir:IIndexedItemRenderer = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
> + var ir:IIndexedItemRenderer;
> + if(_unusedRenderers.length > 0)
> + ir = _unusedRenderers.pop();
> +
> + else
> + ir = itemRendererFactory.createItemRenderer() as IIndexedItemRenderer;
>
> var data:Object = event.item;
> dataGroup.addItemRendererAt(ir, event.index);
> @@ -108,7 +87,8 @@ package org.apache.royale.html.beads
> }
>
> sendStrandEvent(_strand,"itemsCreated");
> - sendStrandEvent(_strand,"layoutNeeded");
> + // The itemsCreated handler sends layoutNeeded, so no need to do it here.
> + // sendStrandEvent(_strand,"layoutNeeded");
> }
>
> /**
> @@ -119,7 +99,7 @@ package org.apache.royale.html.beads
> * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> * @royaleignorecoercion org.apache.royale.html.beads.IListView
> */
> - protected function itemRemovedHandler(event:CollectionEvent):void
> + override protected function itemRemovedHandler(event:CollectionEvent):void
> {
> if(!dataProviderExist)
> return;
> @@ -130,7 +110,7 @@ package org.apache.royale.html.beads
> var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
> if (!ir) return; // may have already been cleaned up, possibly when a tree node closes
> dataGroup.removeItemRenderer(ir);
> -
> + _unusedRenderers.push(ir);
> // adjust the itemRenderers' index to adjust for the shift
> var n:int = dataGroup.numItemRenderers;
> for (var i:int = event.index; i < n; i++)
> @@ -147,39 +127,6 @@ package org.apache.royale.html.beads
>
> sendStrandEvent(_strand,"layoutNeeded");
> }
> -
> - /**
> - * @private
> - * @royaleignorecoercion org.apache.royale.collections.ICollectionView
> - * @royaleignorecoercion org.apache.royale.core.IIndexedItemRenderer
> - * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
> - * @royaleignorecoercion org.apache.royale.html.beads.IListView
> - */
> - protected function itemUpdatedHandler(event:CollectionEvent):void
> - {
> - if(!dataProviderExist)
> - return;
> -
> - var view:IListView = (_strand as IStrandWithModelView).view as IListView;
> - var dataGroup:IItemRendererOwnerView = view.dataGroup;
> -
> - // update the given renderer with (possibly) new information so it can change its
> - // appearence or whatever.
> - var ir:IIndexedItemRenderer = dataGroup.getItemRendererAt(event.index) as IIndexedItemRenderer;
> -
> - var data:Object = event.item;
> - (itemRendererInitializer as IIndexedItemRendererInitializer).initializeIndexedItemRenderer(ir, data, event.index);
> - ir.data = data;
> - }
> -
> - override protected function get dataProviderLength():int
> - {
> - return dataProviderModel.dataProvider.length;
> - }
> -
> - override protected function getItemAt(i:int):Object
> - {
> - return dataProviderModel.dataProvider.getItemAt(i);
> - }
> +
> }
> }
> \ No newline at end of file
>